DEV Community

Aleksander Sekowski
Aleksander Sekowski

Posted on

How vastlint's Validation Rules Were Extracted from the VAST PDF Specs and XSD Schemas

The IAB Tech Lab publishes VAST as two artifacts: a PDF specification document and a set of XSD schema files. The PDF is the normative authority. It defines what a conformant VAST response must, should, and may contain. The XSD describes the document structure in machine-readable form but has gaps; it does not cover business logic, ordering constraints, or anything involving URLs. Building a linter against VAST meant reading both and treating them as complementary sources of truth, not interchangeable ones.

The PDF extraction was manual and slow. Each version of the spec (2.0, 3.0, 4.0, 4.1, 4.2, 4.3) was read cover to cover and every normative statement was tagged by element, attribute, and constraint type. A rule like "InLine must contain AdTitle" comes directly from section language in the 2.0 spec that predates all subsequent versions and has never been relaxed. Deprecations were tracked version by version: conditionalAd deprecated in 4.1, Survey deprecated in 4.1, the fullscreen/exitFullscreen tracking events removed in 4.0. Each one becomes a versioned rule rather than a blanket error, so a VAST 3.0 document is not penalised for things that only matter in 4.x.

The XSD pass was more systematic. The schemas enumerate valid attribute values, allowed child elements, and content models for every element across spec versions. These became structural rules: unknown attributes, unknown child elements, invalid enum values for things like delivery, adType, renderingMode, and tracking event names. A third category of rules does not come from either the PDF or the XSD. It comes from what goes wrong in production. HTTPS enforcement on MediaFile and tracking URLs, duplicate Impression URLs causing billing disputes, missing quartile tracking events, the VPAID-in-CTV footgun: these are rules sourced from patterns that show up repeatedly in real VAST traffic. The source tag on each rule (VastSpec, VastXsd, IndustryBestPractice, Inferred, etc.) reflects exactly where it came from.

The full rule set is listed below. Each rule ID links to its dedicated page on vastlint.org with the exact spec section, severity, fix guidance, and examples.


Rule ID Description Source
VAST-2.0-root-element Root element must be <VAST> VAST Spec
VAST-2.0-root-version <VAST> must have a version attribute VAST Spec
VAST-2.0-root-version-value VAST version attribute must be a recognised version string VAST XSD
VAST-2.0-root-has-ad-or-error <VAST> must contain at least one <Ad> or <Error> VAST Spec
VAST-4.0-wrapper-root-error <VAST> root contains both <Ad> and <Error> elements (invalid per VAST 4.0) VAST Spec
VAST-2.0-ad-has-inline-or-wrapper Each <Ad> must contain exactly one <InLine> or <Wrapper> VAST Spec
VAST-2.0-inline-adsystem <InLine> must contain <AdSystem> VAST Spec
VAST-2.0-inline-adtitle <InLine> must contain <AdTitle> VAST Spec
VAST-2.0-inline-impression <InLine> must contain at least one <Impression> VAST Spec
VAST-2.0-inline-creatives <InLine> must contain <Creatives> with at least one <Creative> VAST Spec
VAST-4.1-adservingid-present <InLine> must contain <AdServingId> (VAST 4.1+) VAST Spec
VAST-4.0-universaladid-present <Creative> must contain <UniversalAdId> (VAST 4.0+) VAST Spec
VAST-4.0-universaladid-idregistry <UniversalAdId> must have an idRegistry attribute VAST Spec
VAST-4.0-universaladid-idvalue <UniversalAdId> missing required idValue attribute (VAST 4.0) VAST Spec
VAST-4.1-universaladid-idvalue-removed <UniversalAdId> idValue attribute was removed in VAST 4.1 VAST Spec
VAST-4.1-universaladid-content <UniversalAdId> must have text content in VAST 4.1+ VAST Spec
VAST-2.0-linear-duration <Linear> must contain <Duration> VAST Spec
VAST-2.0-linear-mediafiles <Linear> must contain <MediaFiles> with at least one <MediaFile> VAST Spec
VAST-2.0-mediafile-delivery <MediaFile> must have a delivery attribute VAST Spec
VAST-2.0-mediafile-delivery-enum <MediaFile> delivery must be "progressive" or "streaming" VAST XSD
VAST-2.0-mediafile-type <MediaFile> must have a type attribute VAST Spec
VAST-2.0-mediafile-dimensions <MediaFile> must have width and height attributes VAST Spec
VAST-2.0-wrapper-adsystem <Wrapper> must contain <AdSystem> VAST Spec
VAST-2.0-wrapper-impression <Wrapper> must contain at least one <Impression> VAST Spec
VAST-2.0-wrapper-vastadtaguri <Wrapper> must contain <VASTAdTagURI> VAST Spec
VAST-2.0-companion-resource <Companion> must contain at least one StaticResource, IFrameResource, or HTMLResource VAST Spec
VAST-2.0-nonlinear-resource InLine <NonLinear> must contain at least one StaticResource, IFrameResource, or HTMLResource VAST Spec
VAST-2.0-wrapper-depth Wrapper chain depth exceeds the configured maximum VAST Spec
VAST-2.0-ad-sequence Mixed use of sequence attribute across <Ad> elements in a pod VAST Spec
VAST-2.0-duration-format <Duration> value does not match HH:MM:SS[.mmm] format VAST Spec
VAST-2.0-text-only-element Text-only element contains a child element VAST XSD
VAST-2.0-unknown-attribute Element has an attribute not defined in the VAST spec VAST XSD
VAST-2.0-inline-unknown-child <InLine> contains an unrecognised child element VAST XSD
VAST-2.0-wrapper-unknown-child <Wrapper> contains an unrecognised child element VAST XSD
VAST-2.0-creatives-unknown-child <Creatives> may only contain <Creative> elements VAST XSD
VAST-2.0-creative-unknown-child <Creative> contains an unrecognised child element VAST XSD
VAST-2.0-linear-unknown-child <Linear> contains an unrecognised child element VAST XSD
VAST-2.0-trackingevents-unknown-child <TrackingEvents> may only contain <Tracking> elements VAST XSD
VAST-2.0-mediafiles-unknown-child <MediaFiles> contains an unrecognised child element VAST XSD
VAST-2.0-extensions-unknown-child <Extensions> may only contain <Extension> elements VAST XSD
VAST-2.0-videoclicks-unknown-child <VideoClicks> contains an unrecognised child element VAST XSD
VAST-2.0-nonlinearads-unknown-child <NonLinearAds> contains an unrecognised child element VAST XSD
VAST-2.0-nonlinear-unknown-child <NonLinear> contains an unrecognised child element VAST XSD
VAST-2.0-companionads-unknown-child <CompanionAds> may only contain <Companion> elements VAST XSD
VAST-2.0-companion-unknown-child <Companion> contains an unrecognised child element VAST XSD
VAST-2.0-creativeextensions-unknown-child <CreativeExtensions> may only contain <CreativeExtension> elements VAST XSD
VAST-2.0-extension-misplaced-element <Extension> contains an element that has a dedicated location in the VAST spec VAST Spec
VAST-2.0-creative-extension-misplaced-element <CreativeExtension> contains an element that has a dedicated location in the VAST spec VAST Spec
VAST-2.0-mediafile-https <MediaFile> URL uses HTTP instead of HTTPS, blocked by mixed-content policy on secure inventory Industry Best Practice
VAST-2.0-tracking-https Tracking or click URL uses HTTP instead of HTTPS, blocked by mixed-content policy, measurement signal lost Industry Best Practice
VAST-2.0-url-empty URL field is empty VAST Spec
VAST-2.0-url-invalid URL field does not appear to be a valid URI RFC 3986
VAST-2.0-parse-error XML parse error, document may be malformed XML
VAST-2.0-version-mismatch Declared version does not match structural signals Inferred
VAST-2.0-duplicate-impression Duplicate <Impression> URL within the same <Ad>, causes double-counted billing and disputes Industry Best Practice
VAST-2.0-nonlinear-dimensions <NonLinear> missing width or height VAST Spec
VAST-2.0-companion-dimensions <Companion> missing width or height VAST Spec
VAST-2.0-flash-mediafile Flash-based MediaFile type is no longer supported Inferred
VAST-2.0-linear-tracking-quartiles <Linear> has no standard quartile tracking events, impression serves but measurement system receives no signal Industry Best Practice
VAST-3.0-icons-unknown-child <Icons> may only contain <Icon> elements VAST XSD
VAST-3.0-icon-unknown-child <Icon> contains an unrecognised child element VAST XSD
VAST-3.0-iconclicks-unknown-child <IconClicks> contains an unrecognised child element VAST XSD
VAST-3.0-progress-offset <Tracking event="progress"> requires an offset attribute VAST Spec
VAST-3.0-progress-offset-format Tracking progress offset does not match required format VAST Spec
VAST-3.0-icon-attrs Icon missing recommended attributes (program/width/height/position) VAST Spec
VAST-3.0-icon-program <Icon> missing required program attribute VAST Spec
VAST-3.0-icon-width <Icon> missing required width attribute VAST Spec
VAST-3.0-icon-height <Icon> missing required height attribute VAST Spec
VAST-3.0-icon-xposition <Icon> missing required xPosition attribute VAST Spec
VAST-3.0-icon-yposition <Icon> missing required yPosition attribute VAST Spec
VAST-3.0-icon-resource <Icon> must have at least one resource element VAST Spec
VAST-3.0-skipoffset-format Linear skipoffset does not match HH:MM:SS[.mmm] or n% format VAST Spec
VAST-3.0-skip-event-no-skipoffset skip tracking event present but Linear has no skipoffset attribute VAST Spec
VAST-3.0-minmaxbitrate-pair <MediaFile> must have both minBitrate and maxBitrate or neither VAST Spec
VAST-3.0-bitrate-conflict <MediaFile> has both bitrate and minBitrate/maxBitrate VAST Spec
VAST-3.0-pricing-model <Pricing> missing required model attribute VAST Spec
VAST-3.0-pricing-currency <Pricing> missing required currency attribute VAST Spec
VAST-3.0-pricing-model-case <Pricing> model value should be lowercase in VAST 3.0 (cpm/cpc/cpe/cpv) VAST XSD
VAST-3.0-pricing-currency-format <Pricing> currency attribute must be a 3-letter ISO-4217 code ISO 4217
VAST-3.0-companion-required-attr <CompanionAds> required attribute must be all, any, or none VAST XSD
VAST-4.0-conditionalad conditionalAd attribute is deprecated as of VAST 4.1 VAST Spec
VAST-4.0-wrapper-clickthrough <ClickThrough> inside Wrapper <VideoClicks> was removed in VAST 4.0 (re-allowed in 4.2) VAST Spec
VAST-4.0-tracking-event-removed fullscreen/exitFullscreen tracking events were removed in VAST 4.0 VAST Spec
VAST-4.0-mediafile-apiframework <MediaFile apiFramework> is deprecated in VAST 4.0+, use <InteractiveCreativeFile> VAST Spec
VAST-4.0-category-authority <Category> missing required authority attribute VAST Spec
VAST-4.0-companion-clicktracking-id <CompanionClickTracking> missing required id attribute VAST Spec
VAST-4.0-interactive-creative-no-api <InteractiveCreativeFile> should have an apiFramework attribute VAST Spec
VAST-4.1-adservingid-present <InLine> must contain <AdServingId> (VAST 4.1+) VAST Spec
VAST-4.1-ad-serving-id-empty <AdServingId> is present but empty Inferred
VAST-4.1-survey-deprecated <Survey> is deprecated as of VAST 4.1 VAST Spec
VAST-4.1-vpaid-apiframework apiFramework="VPAID" is deprecated as of VAST 4.1 VAST Spec
VAST-4.1-mezzanine-delivery <Mezzanine> missing required delivery attribute VAST Spec
VAST-4.1-mezzanine-type <Mezzanine> missing required type attribute VAST Spec
VAST-4.1-mezzanine-width <Mezzanine> missing required width attribute VAST Spec
VAST-4.1-mezzanine-height <Mezzanine> missing required height attribute VAST Spec
VAST-4.1-mezzanine-recommended <MediaFiles> has no <Mezzanine>, ad-stitching servers may reject in CTV/SSAI contexts Industry Best Practice
VAST-4.1-verification-no-resource <Verification> should have JavaScriptResource or ExecutableResource VAST Spec
VAST-4.1-verification-vendor <Verification> is missing required vendor attribute VAST Spec
VAST-4.1-blockedadcategories-no-authority <BlockedAdCategories> should have authority attribute VAST Spec
VAST-4.1-interactive-creative-type <InteractiveCreativeFile> should have a type attribute identifying the MIME type IANA Media Types
VAST-4.1-js-resource-apiframework <JavaScriptResource> is missing required apiFramework attribute VAST Spec
VAST-4.1-exec-resource-apiframework <ExecutableResource> is missing required apiFramework attribute VAST Spec
VAST-4.1-exec-resource-type <ExecutableResource> is missing required type attribute VAST Spec
VAST-4.1-tracking-event-value Tracking event attribute not in the valid set for this VAST version VAST XSD
VAST-4.1-adtype-value Ad adType must be video, audio, or hybrid VAST XSD
VAST-4.1-companion-renderingmode-value Companion renderingMode must be default, end-card, or concurrent VAST XSD
VAST-4.1-vpaid-in-interactive-context VPAID MediaFile alongside InteractiveCreativeFile, VPAID unsupported in CTV, zero fill Industry Best Practice
VAST-4.2-closedcaptionfiles-unknown-child <ClosedCaptionFiles> may only contain <ClosedCaptionFile> elements VAST XSD
VAST-4.2-icon-fallback-image-width-height <IconClickFallbackImage> should have width and height attributes VAST Spec
VAST-4.3-js-resource-browser-optional <JavaScriptResource> should have a browserOptional attribute VAST Spec
SIMID-1.0-simid-type-required <InteractiveCreativeFile apiFramework="SIMID"> must have type="text/html" SIMID Spec
SIMID-1.0-simid-url-empty <InteractiveCreativeFile apiFramework="SIMID"> must contain a non-empty URL SIMID Spec
SIMID-1.0-simid-url-https <InteractiveCreativeFile apiFramework="SIMID"> URL must use HTTPS SIMID Spec
SIMID-1.0-simid-variable-duration-value <InteractiveCreativeFile> variableDuration attribute must be "true" when present SIMID Spec
SIMID-1.0-simid-mediafile-required Linear SIMID ad must include a video/audio <MediaFile> alongside the interactive creative SIMID Spec
SIMID-1.1-nonlinear-simid-no-iframe <NonLinear apiFramework="SIMID"> must contain an <IFrameResource> SIMID Spec
SIMID-1.1-iframe-simid-type-required <IFrameResource> in SIMID <NonLinear> should have type="text/html" SIMID Spec
SIMID-1.1-iframe-simid-url-empty <IFrameResource> in SIMID <NonLinear> must contain a non-empty URL SIMID Spec
SIMID-1.1-iframe-simid-url-https <IFrameResource> in SIMID <NonLinear> URL must use HTTPS SIMID Spec

Top comments (0)