Vulnerabilities
Chromium Reused an Incompatible AV1 Decoder Context (CVE-2026-15114)
CVE-2026-15114 lets a crafted AV1 sequence change allocation-sensitive coding tools while keeping its visible dimensions stable, so old Chromium builds reuse an undersized hardware context and can perform out-of-bounds reads or writes.

In this article
1 The second 720p sequence arrived, but the cabinet did not grow
1.1 The same visible format carried a different internal contract
The failure begins at an unremarkable transition. A hardware decoder has already accepted one coded video sequence, allocated its platform context, and displayed a 1280×720 picture. A second sequence header arrives in the same stream. Its profile remains zero, its samples remain eight bits, its chroma remains 4:2:0, and its maximum frame rectangle has not moved by one pixel. A player looking only at the public output description sees no reason to replace anything. Inside the sequence header, however, a different collection of coding tools has just become legal.
Think of the first context as a cabinet ordered for a known workshop. At creation time the backend chooses reference surfaces, probability state, motion-vector storage, loop-filter scratch, restoration lines, and intermediate pictures according to the features advertised by the sequence. When a feature is absent, a driver may omit its drawer or make that drawer smaller. That is a sensible optimization because GPU memory is expensive, surfaces are alignment-sensitive, and fixed-function firmware often expects an exact resource layout for the lifetime of a decoding session.
The second header does not ask for a larger canvas. It asks the worker behind the canvas to pick up tools that were not on the original order. Order hints may make temporal relationships available; reference-frame motion vectors may make previously decoded motion state consumable; joint and masked compound modes may need more predictor machinery; super-resolution, CDEF, and restoration may add processing stages with their own working storage. None of these facts must change the width, height, profile, depth, or chroma values returned to the application.
AV1 permits a sequence header to describe the capabilities of a coded video sequence before individual frame headers select legal operations. Chromium's parser converts those bits into an ObuSequenceHeader. The parsed structure is trustworthy as a representation of the input, but its values still originate in untrusted media. The next decision is a lifetime decision: can the platform object built for the previous structure safely accept pictures governed by the new one? A false answer must travel far enough to recreate the object before submission resumes.
This distinction separates display configuration from resource configuration. Display configuration answers what the consumer receives: dimensions, visible rectangle, color space, bit depth, and sampling. Resource configuration answers what the decoder must have internally to produce it. The two sets overlap, but neither contains the other. Treating output equality as context compatibility silently collapses two state machines into one, leaving every private allocation controlled only by the values checked in the narrower state machine.
The July fix is unusually valuable because its commit message states the missing invariant in operational terms. Midstream sequence headers can change coding-tool flags without producing a conventional configuration change. Chromium could then reuse the existing hardware context and its memory pools. If a newly enabled path expected scratch that had not been allocated when that context was created, backend state could become desynchronized and out-of-bounds reads or writes could follow. That description links bitstream syntax, Chromium lifetime, and driver memory behavior without inventing a universal crash address.
1.2 The parser saw a new sequence while the reset verdict stayed incomplete
The parser did its part. When a new sequence header appeared, sequence_header_changed() told AV1Decoder::DecodeInternal() that the coded sequence had changed. Chromium validated the new header, derived its familiar output fields, and compared the old and new structures. The dangerous outcome did not come from missing the header. It came from asking an incomplete compatibility question after the header had already been recognized.
Before the final patch, RequiresHardwareContextReset() examined four structural fields. A change in use_128x128_superblock could alter block organization. A change in film_grain_params_present could change synthesis support. CDEF and loop restoration each introduced processing resources worth rebuilding around. Those checks were legitimate, and their presence shows that Chromium already understood a stable output format could hide an incompatible context. The coverage simply stopped too early.
Eleven other switches remained outside the verdict. When all conventional output fields and those four original checks stayed equal, structural_change remained false. The decoder installed the new header as current state and cleared its reference frames, but it did not send the configuration event that caused the owner to replace the platform context. Clearing logical references could not create missing scratch surfaces or resize a private driver pool. It reset one part of history while retaining another part whose assumptions had just expired.
This is a common shape in lifetime failures. The code has a correctly named predicate, a clear call site, and a safe recovery path; the defect lives in the inventory behind the predicate. The helper's presence can suggest that lifetime is covered even while backend-specific creation code depends on more fields. Security requires those dispersed facts to meet in one complete comparison at the shared decision point.
The exact old field set also explains why ordinary videos could exercise the decoder for years without making the gap obvious. Many streams keep one sequence header, use a stable tool profile, or change dimensions at the same time as their tools. A dimension change already emits kConfigChange, masking the missing structural predicate. The revealing input holds every older trigger still and moves only the previously unlisted switches. It is less a spectacular malformed file than a carefully isolated contract change.
The bug therefore lived between two successful operations. Parsing the new syntax succeeded. The old context had successfully decoded the earlier sequence. Combining them was unsafe because success belonged to different points in time. The second sequence inherited a cabinet built under the first sequence's rules, and no type system in the driver API could express that the cabinet had expired. Chromium's Boolean reset verdict carried that entire temporal obligation.
A durable audit begins by building the inventory independently of the helper. Trace every sequence-header member consumed when generic or platform code creates an AV1 session, surface pool, firmware parameter block, or persistent reference resource. For each value, record its consumer, the creation decision it influences, and the comparison that invalidates an existing context. Comparing that set with the helper reveals omissions that a line-by-line review of the helper alone cannot see.
The inventory should also classify lifetime. Some syntax is consumed for one frame, some persists across a coded video sequence, and some shapes the platform session itself. A value used only in a per-frame command can safely change under an established session if the API permits it. A value used to size or configure persistent state needs a sequence-transition invalidator. CVE-2026-15114 existed because eleven values with that second role were absent from the shared lifetime verdict.
Coverage tests can derive directly from that classification. Hold every public format predicate equal, mutate one context-sensitive value, and require a new generation before submission. Where AV1 dependencies make an isolated mutation invalid, use the smallest legal group and assert every parsed member. This turns backend knowledge into executable coverage and gives future additions a clear place to extend the suite.
Parser rejection is a separate property. A malformed header that never reaches the accelerator can test syntax validation, but it cannot prove legal sequence changes rebuild persistent resources. The security regression must remain conforming enough to traverse normal decode, because the dangerous pair consisted of a valid new header and a valid old object whose validity belonged to the previous sequence.
2 A reset decision stood between the parser and the accelerator
The code and response path can be reduced to one line: in fixed commit 48c725cd3ed1, media/gpu/av1_decoder.cc completes RequiresHardwareContextReset(), and AV1Decoder::DecodeInternal() feeds that verdict into the kConfigChange branch before a new picture can be submitted; the regression is in media/gpu/av1_decoder_unittest.cc at the same commit. Chrome's fixed builds are 150.0.7871.115 or 150.0.7871.114 on Windows and macOS, and 150.0.7871.114 on Linux. Permanent remediation is update plus a full restart of the process that owns decoding. If an update is temporarily impossible, hardware AV1 decoding can be disabled only as a time-bounded control, with the real application, child processes, and embedded views verified on the software path.
2.1 DecodeInternal() assembled the change verdict
Following the call path removes the mystery from the reset. AV1Decoder::SetStream() receives a decoder buffer and constructs a libgav1 ObuParser over it. If Chromium already holds a sequence header, it gives that state back to the parser so parsing can continue when syntax spans adjacent input buffers. Decode() then enters DecodeInternal(), where temporal units, sequence headers, frame headers, tiles, and output decisions become one ordered transaction.
Once parser_->sequence_header_changed() is true, the function obtains the new sequence header and rejects unsupported spatial-layer arrangements. It derives maximum dimensions, visible rectangle, profile, bit depth, chroma sampling, and color information. These are the values an application recognizes as video configuration. In parallel, if current_sequence_header_ exists, the function computes structural_change through RequiresHardwareContextReset(). That second result represents the backend contract the application does not see.
The two branches meet in one condition. Conventional format differences or a true structural_change cause Chromium to update the decoder's public configuration fields, cancel the automatic cleanup guard for the current frame, and return kConfigChange. Cancellation matters because the caller will re-enter after it has responded to the new configuration; the decoder must preserve enough state to resume at the correct point. The return is therefore a controlled pause, not an error.
Before evaluating that return, the code updates current_sequence_header_ and clears reference frames when the sequence changes. That ordering can look surprising in isolation, but the regression captures the expected protocol: the decoder exposes the new configuration, the owner rebuilds resources, and a subsequent call continues consumption. What the security fix changes is the set of transitions that are allowed to enter this protocol. It does not redesign the parser or the accelerator interface.
The ordinary configuration predicates still have an important role. A larger maximum frame size, a profile shift, another bit depth, different chroma sampling, or a color-space change already tells the owner that output resources must be reconsidered. The structural predicate fills the hole left by transitions that are invisible to those values. Its position alongside them is evidence that allocation-sensitive tool flags belong at the same lifetime gate even though they do not belong in the public display format.
A downstream integration must trace the Boolean all the way to the return. Finding the fifteen comparisons is insufficient if a merge conflict disconnects their result from the configuration condition; conversely, a vendor may implement an equivalent reset under another helper name. The invariant is observable at the handoff: after an allocation-sensitive field changes, no picture governed by the new header can reach an accelerator created under the old header.
2.2 kConfigChange was the only safe gate
The caller sees kConfigChange as a demand to reconcile ownership. Chromium's codec-independent decoder describes the new requirements; the platform path owns surfaces, protected sessions, command buffers, and any driver object whose layout was decided at creation. The return gives that owner a moment when no new picture has been submitted. It can drain or discard prior work, destroy the incompatible context, allocate a replacement, and then call back into the decoder.
If the return never happens, the remainder of DecodeInternal() follows the normal path. It asks the accelerator to create an AV1Picture, prepares parsed frame state, and eventually invokes DecodeAndOutputPicture(). From there accelerator_->SubmitDecode() receives the new sequence header alongside surfaces tied to the retained platform object. Both arguments look individually valid. Their lifetime relationship is the part Chromium failed to validate.
ClearReferenceFrames() cannot substitute for context recreation. Reference slots are Chromium's logical view of pictures available for prediction. Hardware scratch, codec heaps, line buffers, or firmware tables may be attached to the context itself and survive logical reference clearing. The fix treats a tool-contract change as a reason to rebuild the owner of those hidden resources. This aligns the visible state reset with the state that only the backend can see.
A full reconstruction avoids a partial repair. Growing one known scratch buffer might stop a crash on one device while leaving another backend's tables or command templates stale. Shared code only decides that the contract changed; platform code reapplies the new header to every creation-time decision. Configuration return, old-context retirement, new-context creation, and submission generation therefore form a stable acceptance trace without requiring an actual out-of-bounds access.
The asynchronous handoff has two ordering requirements. Work submitted under sequence A must drain or pass its fence before old resources retire, and sequence B must wait until the new generation is ready. Routing the transition through the existing kConfigChange path reuses the synchronization model already established for format changes, preventing both early destruction and late construction.
The correct trace has a clean break: parser reports sequence change; the reset predicate returns true; reference state is cleared; Decode() yields kConfigChange; the caller reconstructs the accelerator context; a later call creates and submits the next picture. The vulnerable trace lacks only the middle yield and reconstruction. That small missing interval is where a valid 720p stream acquired out-of-bounds consequences.
kConfigChange is recoverable control flow, not a parse failure. Wrappers around AcceleratedVideoDecoder must propagate it to the component that owns the platform object and pause their decode loop; treating it as “try again,” or replacing only an unrelated output surface, defeats the fix. Acceptance must also distinguish draining, flushing buffered decode state, clearing logical references, and reconstructing the context. Only the last operation creates platform resources from the new sequence, so proof must reach the new generation and its first submission.
kConfigChange before any picture carrying the new contract reached submission.3 Fifteen switches described a resource inventory
3.1 The complete comparison mapped coding tools to context lifetime
The final helper reads like a row of inequalities, but it is easier to understand as a resource inventory. The original four entries remain: use_128x128_superblock, film_grain_params_present, enable_cdef, and enable_restoration. The July commit adds enable_superres, enable_filter_intra, enable_intra_edge_filter, enable_interintra_compound, enable_masked_compound, enable_warped_motion, enable_dual_filter, enable_order_hint, order_hint_bits, enable_jnt_comp, and enable_ref_frame_mvs.
use_128x128_superblock belongs in the original four because it changes the basic granularity used to divide and traverse a picture. Fixed-function decoders can organize metadata, edge caches, and scheduling batches around that choice. Equal maximum dimensions do not prove that a context organized for smaller superblocks can accept the alternate layout.
film_grain_params_present declares whether sequence frames may carry film-grain parameters. An implementation may synthesize grain during output and reserve parameter state, randomization state, or an extra surface for that stage. The visible rectangle need not change, yet the route from reconstructed picture to final output does.
enable_cdef and enable_restoration control separate in-loop processing stages. CDEF uses directional constraints to reduce ringing; loop restoration can select Wiener or self-guided filtering. Driver or firmware code can reserve line neighborhoods, coefficients, and intermediate samples for these stages. A context created with either stage disabled has no general promise that those work areas exist.
enable_superres permits a frame to be reconstructed at a narrower coded width and upscaled to its output width. The application can still receive the same 1280×720 picture while the internal pipeline needs different pitches, temporary rows, and scaling work. This makes super-resolution an independent context input even when maximum dimensions stay equal.
enable_filter_intra enables filtered intra predictors, while enable_intra_edge_filter changes preparation of neighboring edge samples. Both operate inside blocks and can leave every sequence-level output dimension untouched. Backends may use their values to select kernel sets, upload tables, or provision local scratch at session construction.
enable_interintra_compound allows an inter predictor to be combined with an intra predictor. enable_masked_compound enables masked blending of predictors. Those routes can need more intermediate predictor data, weights, and reads than a single-reference route. The finished picture has the same geometry even though the number and lifetime of intermediate resources can differ.
enable_warped_motion enables warped prediction with transformation parameters, expanded sampling behavior, and edge handling. It can alter reference-surface access and the command sequence selected by firmware. Treating it as a per-frame toggle inside a session created without the capability would leave backend support unproven.
enable_dual_filter permits horizontal and vertical interpolation to choose different filters. That adds filter-selection and coefficient state during prediction without changing decoded dimensions. Some hardware APIs model such capability in session creation data, which is exactly the kind of private dependency the shared reset decision must respect.
enable_order_hint controls whether relative display-order information has meaning, and order_hint_bits determines its range. A width change can affect masks, comparisons, and table representation even when the controlling feature remains enabled. Comparing both fields prevents an old context from interpreting new sequence state with the previous width.
enable_jnt_comp permits compound prediction weighted by temporal distance. Its calculations are tied to order hints and can require weight or intermediate-predictor state. enable_ref_frame_mvs adds another lifetime dependency: reference slots may carry motion-field surfaces or metadata whose format and presence were chosen when the context was created.
Viewed field by field, the helper is not an arbitrary collection of feature flags. Its inputs span block organization, reconstruction filters, prediction kernels, reference metadata, and intermediate storage. Chromium resets the whole context because its shared layer cannot prove that every Windows, Linux, ChromeOS, and device backend can safely upgrade every combination in place.
The list also does not claim that enabling a tool always allocates more bytes. Some backends reserve a maximum-sized pool, some change firmware state only, and others size each resource precisely. The security decision asks whether old allocation assumptions still have evidence behind them. Running the backend's construction path again restores that evidence without guessing the direction of the size change.
Comparing order_hint_bits even when another header field controls its use is defensive lifecycle accounting. The helper answers whether the entire context contract is unchanged, not whether a particular frame will immediately exercise every path. A fresh context can normalize dependent state according to the new sequence. Reusing the old one asks shared code and every backend to agree on which dormant differences are harmless, a much larger and less stable proof obligation.
The helper uses direct equality. It does not assign risk weights, calculate memory sizes, or predict which driver will fail. Any listed difference is enough to return true. This conservative Boolean is appropriate because context recreation already exists as the supported transition mechanism, and the cost occurs only when the coded video sequence changes. The security gain comes from preventing cross-sequence state reuse under assumptions the generic layer cannot inspect.
The list also creates a maintenance obligation. If a future AV1 integration uses another sequence field during platform context creation, that field must join the shared reset predicate or be handled by an equivalently strong backend-independent mechanism. Code review can make this explicit: every new creation-time read of sequence syntax should identify the lifetime comparison that invalidates an existing context when the value changes.
3.2 New syntax and old allocations formed an invalid pair
Once the incomplete comparison returns false, the desynchronization is straightforward. Libgav1 has parsed the second sequence and Chromium's current header now authorizes its tools. The driver object still reflects the first sequence. A later frame selects a newly enabled operation, Chromium translates that operation into backend parameters, and fixed-function code follows a path whose supporting memory was never reserved under the old context.
The commit describes out-of-bounds reads and writes as possible results, but it does not publish one backend-independent primitive. That restraint is technically important. On one GPU, a missing scratch allocation may produce a rejected command or a device reset. On another, a firmware index may fall beyond a private buffer. A third implementation may over-allocate and show no visible symptom. The shared defect is the stale allocation contract; the final memory access belongs to platform code.
Out-of-bounds reads can expose adjacent decoder or driver data to later computation, cause invalid references to be consumed, or simply fault. Out-of-bounds writes can corrupt nearby GPU-visible state and carry stronger integrity consequences. The public advisory classifies the issue as an out-of-bounds read and write in Codecs and rates it high severity. Public sources do not establish a stable cross-platform exploitation chain, so response planning should use the confirmed memory-safety impact and the broad media attack surface without inventing device-specific behavior.
The isolation between the browser and GPU process affects consequence, not root cause. Chromium commonly places hardware media operations in a sandboxed process and communicates with privileged drivers through operating-system interfaces. Memory corruption may occur in user-mode media code, a vendor library, kernel driver state, or firmware-managed memory depending on the selected backend. Sandboxing and driver validation can reduce or alter impact, yet neither repairs the stale context that lets incompatible state reach them.
The sequence header itself need not violate the AV1 specification. Two coded video sequences can legitimately advertise different tool capabilities. A secure implementation must treat that legal transition as hostile input from a lifetime perspective because the media source controls when it occurs. Rejecting all such changes would damage compatibility. Rebuilding the context preserves standards behavior and keeps the trust decision where Chromium already handles reconfiguration.
Reference clearing illustrates the split state clearly. Chromium can erase its array of reference pictures and prevent new frames from referring to pictures from the previous sequence. The platform context can still retain heaps, probability buffers, command templates, or capability bits chosen under the old header. Logical emptiness above the accelerator does not prove physical compatibility below it. The reset event has to complete the ownership handoff.
A crash-only investigation often starts too late. Once the driver faults, the sequence transition and context creation that caused it may be several asynchronous calls behind the top stack frame. Instrumentation around the reset predicate and submission gate exposes the invariant earlier: record the old and new fifteen-field vectors, the resulting structural_change, the context identifier, and whether a new identifier exists before the next submission. This evidence can distinguish stale-context execution from unrelated GPU instability.
The remedy also avoids embedding exploit assumptions in deployment. Administrators do not need to determine which exact field produces corruption on each GPU before upgrading. If a product contains the vulnerable decision and can accept attacker-influenced AV1 through hardware acceleration, it needs the corrected context lifetime. Backend testing then verifies the fix and catches integration regressions; it does not decide whether the shared source defect deserves remediation.
Platform routes amplify this uncertainty. Windows can pass through operating-system media interfaces and vendor user-mode drivers; Linux and ChromeOS can use VA-API, V4L2, or device-specific acceleration layers. Ownership, error reporting, and device-reset behavior differ. The shared fix ends the stale context before those branches, at the last point where one invariant can cover all of them.
Protected playback can add secure surfaces, restricted mappings, and session state. The public patch does not limit the defect to one content-protection mode, so an inventory cannot dismiss a product simply because it usually handles encrypted streams. If the same AV1Decoder controls lifetime, source remediation remains the relevant proof.
A driver that rejects an inconsistent command is a possible defensive outcome, not a Chromium guarantee. Validation in one vendor release may catch absent resources while another combination continues. Stopping the mismatch before submission makes correctness independent of every driver's ability to rediscover the stale-session error.
Likewise, a laboratory device that never crashes proves only that its current combination produced no visible fault. Over-allocation, a frame that never selects the enabled tool, silent recovery, or missing telemetry can hide the symptom. The reset predicate and configuration event are deterministic evidence; smooth playback is a compatibility observation.
Reconstruction belongs at sequence-header acceptance, not at the first frame that happens to exercise an enabled tool. The header has already granted later frames permission to select those paths, command construction may prepare tables or capability parameters before obvious use, and an asynchronous backend can queue work before generic code notices. Returning control to the owner at the header-acceptance point supplies one deterministic gate for every platform instead of asking shared code to guess when a resource becomes “actually used.”
A hardware capability query answers a different question from context compatibility. A driver can report that the device supports restoration, warped motion, or reference-frame motion vectors in general; that proves a session for sequence B can be created, not that a session created under sequence A provisioned those resources. Backend evidence should therefore retain the global capability result, the creation descriptor or fifteen-field digest for the current context, and the generation used by submission. Joining those observations separates “the GPU can do it” from “this object was built to do it.”
The public materials do not name the exact buffer, offset, degree of attacker control, or a sandbox-escape continuation. Keeping those details unclaimed does not weaken the root cause. The commit supports a precise model: new syntax authorizes a path whose required context resources may be absent, causing backend state desynchronization and possible out-of-bounds access.
That evidence is already sufficient for urgent action. Hardware video decoding receives large volumes of untrusted media from browsers and embedded applications, and Chrome assigned a high severity. Accurate limits simply leave clear attachment points for later driver advisories, crash artifacts, or expanded disclosure without rewriting the established lifetime analysis.
4 Two byte arrays held the canvas still
4.1 Sequence A and sequence B changed the tool contract alone
The regression test turns the lifetime argument into two compact inputs. kSequenceA and kSequenceB are byte arrays embedded in av1_decoder_unittest.cc. They are not broad conformance clips with many moving parts. Each carries enough AV1 structure for the parser and mock accelerator to traverse the relevant path, while the second sequence isolates the tool-flag transition that older reset logic missed.
Comments beside the test state the negative controls explicitly. Both sequences use the same dimensions, profile, bit depth, chroma sampling, and 128×128-superblock choice. Those equalities matter because any conventional format difference would trigger kConfigChange even in the vulnerable implementation. If the test changed width at the same time as order hints, a green result would prove only the old width check still worked.
Sequence A establishes the baseline. Its parsed header has order hints disabled and reference-frame motion vectors disabled. The mock accelerator creates a picture, accepts a decode submission, and outputs it. The test retains the sequence header observed during submission so assertions can inspect what the decoder actually handed to the accelerator. This avoids inferring parser state solely from handcrafted bytes.
Sequence B keeps the conventional configuration equal and flips the allocation-sensitive set used by the regression. Its observed header enables order hints and reference-frame motion vectors, and its order_hint_bits value differs. The test also covers the broader tool-flag combination encoded by the new sample. The point is not that one particular flag alone owns every backend failure; the point is that the old four-field comparison still sees equality while the corrected fifteen-field comparison sees a new contract.
The mock expectations keep the decoder honest on both sides of the gate. CreateAV1Picture(), SubmitDecode(), and OutputPicture() are expected for each input as decoding resumes after configuration handling. A test that stopped immediately after detecting a header change could miss a state-consumption bug. By completing both pictures, the regression demonstrates that the pause is recoverable and that the second sequence reaches submission under the reconstructed configuration.
Equal maximum width and height are asserted from the captured headers, as is equal use_128x128_superblock. The test then asserts the semantic differences for order hints, reference-frame motion vectors, and hint width. These paired assertions are stronger than comparing raw arrays because they show libgav1 parsed the bytes into the intended fields. If the sample is later edited or parser behavior changes, the test will reveal which control moved.
The regression is associated with bug 520565945. That identifier anchors the fixture to the reported failure even while detailed issue access can remain restricted during rollout. For downstream maintainers, the public commit, review, file path, test name, and byte arrays together form a portable evidence package. They can reproduce the lifecycle assertion without needing access to a private crash sample or an affected GPU.
4.2 The second configuration event proved the rebuild occurred
For each byte array, the expected decoder result sequence is kConfigChange and then kRanOutOfStreamData. The first result gives the caller a chance to configure the accelerator for the sequence. The second says the supplied buffer has been consumed after decoding resumes. Requiring this pair twice makes the second configuration event visible as a first-class outcome, not an incidental crash avoidance.
On the old code, sequence A can legitimately cause the initial configuration event because no prior context exists. Sequence B is the differentiator. Its dimensions and earlier structural fields remain equal, so the incomplete helper returns false and the second event disappears. The test therefore fails at the exact protocol checkpoint whose absence enables stale-context submission. No driver memory corruption is required to demonstrate the bug.
On fixed code, any inequality in the full field set makes structural_change true. DecodeInternal() returns before submitting the next picture. The mock test does not construct a real platform driver object, but its result ordering proves the shared decoder has emitted the signal that real owners use to rebuild one. Backend integration tests can then verify destruction and construction around the same event.
This layered testing strategy is safer and more stable than a crash reproducer. A crash would depend on a GPU family, driver revision, allocation layout, and possibly asynchronous scheduling. It might stop crashing after an allocator change while the invalid lifetime remained. The unit test asserts the source-level contract common to every backend. A backend test adds platform ordering. Neither needs to attempt an out-of-bounds access.
The test command is deliberately narrow: media_unittests --gtest_filter=AV1DecoderTest.ConfigChangeOnSequenceHeaderToolFlags. Its value is specificity: the output must show that this fixture matched and executed, and that its two sequence arrays produced the two expected configuration events. A downstream tree may rename the suite only if it preserves the fixture and assertions; a generic media-test pass says nothing about this transition.
Additional field-by-field cases can strengthen a vendor backport. Where AV1 syntax permits, hold the entire header constant and vary one reset field at a time. Dependent features need valid combinations, so the AV1 specification and parser constraints determine which pairs are legal. Each case should assert parsed old and new values, a second kConfigChange, and absence of submission on the old context identifier.
Negative cases are equally useful. Two identical sequence headers should not force unnecessary reconstruction. A dimension change should still take the conventional path. A tool change followed by a malformed frame should emit the configuration event before later decode failure. These cases protect performance and state ordering while keeping the security invariant sharp: compatibility is proven by equality of every creation-sensitive input.
The twin arrays return the story to its opening scene. The application still sees the same 720p format. Only the decoder's private contract changes. The patched test makes that invisible difference visible at one stable observation point, the return from Decode(), before backend-specific behavior can blur the cause.
Several controls pin both sides of the lifetime decision. A→B→A must rebuild on each contract change, while B→B must not rebuild needlessly. A split-buffer case waits for the complete sequence header before producing one transition, and feeding B to a fresh decoder takes only the initial-configuration path. Together they show that the second event comes from compatibility across time, not from B being intrinsically exceptional.
Mock expectations must constrain order rather than merely count calls; otherwise an implementation could submit once on the old context and emit configuration afterward while the test still passed. The arrays must not become unexplained constants either. Preserve the array source and test-binary digests, explain every intended parsed difference and equal-value control, and require both the event and new generation to precede sequence B's SubmitDecode().
An embedded product that cannot run the full media_unittests binary can execute the upstream case in its shared source tree, bind the production library to that revision, and add a device-level context-generation test. Any missing layer remains an explicit evidence gap. Whatever combination is used, sequence B must complete reconfiguration before submission; normal playback on one sample cannot replace that ordering proof.
5 Two commits repaired two layers of the decision
5.1 The June refactor extracted the four-field checkpoint
The first public change landed on June 10 as commit f77363617210dd46fb5b7f765c4da1af718a7393, with parent b4fe89207b09b04c195cce1919492feba57b008d, review 7912486, and commit position #1644968. Its title, “Refactor AV1 sequence header validation to fix hardware context invalidation,” describes a structural repair. It extracted RequiresHardwareContextReset() from the larger sequence-change block and made context invalidation an explicit concept in media/gpu/av1_decoder.cc.
The extracted helper compared four fields: 128×128 superblock use, film-grain presence, CDEF, and restoration. Moving them into one named predicate improved reviewability. It separated output-format comparison from tool-driven context comparison and gave later work a precise extension point. It also reduced the chance that a future edit to conventional configuration logic would accidentally hide these structural checks inside unrelated conditions.
The refactor changed only av1_decoder.cc. It did not add the twin-sequence regression that appears in the final security commit, and its four checks did not cover the eleven fields identified later. A downstream branch can therefore contain the helper name and still remain vulnerable. File shape is an intermediate clue; complete field membership and test behavior are the stronger evidence.
Commit dates matter because the old article timeline had placed this refactor on June 22. The public Gitiles record shows June 10. Accurate chronology helps teams evaluating snapshots built between the two changes. A build after June 10 can look modern during a superficial source comparison while still lacking the July completion. An older base can carry a complete backport and a newer branch can omit or revert it, so ancestry plus the actual diff resolves that ambiguity more reliably than a build date or helper-name search.
The parent commits provide clean diff baselines. Comparing b4fe8920 with f7736361 isolates the extraction and original four-field set; comparing 353326bb94b506c10d0ebe3e40f5b34cbf015ccf with the final fix isolates the eleven additions and test. Keeping the stages separate prevents the security change from being mistaken for formatting around an already complete predicate.
The refactor also reveals an engineering lesson. Naming a lifetime decision is necessary, but the predicate remains only as strong as the resource inventory behind it. Shared decoder code cannot derive that inventory from syntax aesthetics. It has to be informed by every backend's creation-time dependencies and then guarded by tests that move fields outside the public format. The July patch supplies both missing pieces.
5.2 The July fix completed the inventory and locked it into a test
The completion landed on July 1 as commit 48c725cd3ed15bad33f5efad89103dd7cbc11be6, authored by Sangwhan Moon. Its parent is 353326bb94b506c10d0ebe3e40f5b34cbf015ccf, Gerrit review is 8021903, and Chromium commit position is #1655533. Read as a state machine, every added inequality is an invalidation edge between snapshots from two coded video sequences. One changed creation-sensitive fact ends the old context's lifetime; a false result positively claims that the complete field set remains compatible.
The call site stores that claim in structural_change only when a prior header exists. An initial sequence already requires ordinary configuration because there is no accelerator state to reuse. This keeps the helper focused on transitions. It also explains why tests must feed two inputs through one decoder instance: running sequence B in a fresh fixture would never exercise compatibility with sequence A.
After parsing the new header, Chromium assigns it to current_sequence_header_ and clears reference frames. If the combined configuration condition is true, it updates visible configuration and returns. A later decoder invocation resumes with the new header already current. The owner must therefore rebuild in response to the return before calling again. Any downstream adaptation that discards the event and blindly retries on the old context can recreate the vulnerability outside the helper.
The cleanup guard around the current frame is part of that resume protocol. A configuration return is not an ordinary end-of-buffer path, so automatic cleanup cannot erase state required after reconfiguration. The final commit leaves this machinery intact. That narrow scope is useful evidence: the fix activates a mature reconfiguration path for more sequence changes instead of inventing a second pause mechanism with new ownership rules.
The diff changes exactly two files. In media/gpu/av1_decoder.cc, eleven inequalities extend the helper. In media/gpu/av1_decoder_unittest.cc, the new twin-sequence case observes the protocol from both directions: return values prove the pause, mock submissions prove recovery, captured headers bind submissions to their inputs, and equal conventional properties prove tool compatibility caused the event. The source and test therefore preserve one causal chain.
A textual backport can fail in subtle ways. An older libgav1 structure may rename fields, a merge can omit one inequality, a version guard can hide a member in one build, and a platform fork may bypass AV1Decoder for selected GPUs. The embedded arrays are also coupled to the branch's parser and mock interfaces. Maintainers may adapt APIs, but they must preserve equal public format, changed allocation-sensitive state, two configuration events, two completed decode cycles, and assertions over the headers actually submitted.
An equivalent repair can also take another form. A vendor might always recreate its AV1 context on any sequence-header change, or move the full comparison into a platform-neutral configuration object. Such a design can satisfy the invariant even without the upstream helper text, provided no changed sequence reaches an old allocation and the behavior is covered by a same-format tool-transition regression. The vendor should document that equivalence with source or test evidence.
Performance measurements belong in acceptance because more transitions now trigger reconstruction. Representative streams should measure latency, dropped frames, surface churn, and power across hardware families. Any regression must be optimized inside the safe lifetime model. The same review should extend to adjacent hardware codecs: enumerate every sequence value consumed during context creation, identify its invalidation comparison, and exercise a constant-output transition that changes private requirements.
Gitiles and Gerrit supply complementary provenance. Gitiles fixes the landed tree, parent, two-file diff, author, and commit position; review 8021903 preserves the review identity and patch evolution. Chrome's release notice then maps that upstream change into the product line. Downstream evidence should retain all three layers so a source backport, signed package, and running process can be connected without relying on a similar-looking helper name.
The maintained inventory should map every reset field to its platform consumers, resource class, and regression case. Whenever persistent AV1 context construction begins reading another sequence-header member, the change must identify its invalidation rule and add a constant-output transition case. That turns dispersed backend knowledge into an interface obligation and makes omitted creation dependencies visible.
Products compiling several AV1 backends need source, integration, and package evidence for each shipped build variant: run the shared regression in the relevant configuration, verify generation ordering on every enabled platform path, then bind the result to the signed package and feature manifest. A green build with one backend disabled cannot prove another package that enables it.
6 One Chromium decoder reached many hardware backends
6.1 Product versions and commit ancestry answered different questions
Chrome's July 8 stable-channel notice establishes the product release line. It lists CVE-2026-15114 as a high-severity “Out of bounds read and write in Codecs,” credits a Google report dated June 6, and delivers the desktop fixes in Chrome 150.0.7871.115 or 150.0.7871.114 for Windows and macOS, with 150.0.7871.114 for Linux. The adjacent build numbers are part of one security release, so a single universal “less than .115” rule would incorrectly describe some platforms.
Managed Chrome fleets should consume the platform package offered through their normal channel and retain its package identifier, signature result, channel, operating system, and installation time. That record proves delivery against the platform-specific version floor; it does not yet prove which image is executing. The independent process check below supplies that runtime fact.
Chromium-based products do not necessarily inherit Chrome's outer release line on the same day. Electron applications, CEF shells, Qt WebEngine distributions, embedded browsers, test runners, and vendor media products can carry their own Chromium snapshot and patch cadence. For them, commit 48c725cd3ed1 or a documented equivalent backport is the precise source cutoff. The product vendor must map that source fact to a release the organization can deploy.
Commit position #1655533 helps order upstream Chromium snapshots, but ancestry remains stronger. A downstream branch with a higher-looking position can omit, revert, or conflict with the change. A long-term branch with an earlier base can carry an equivalent patch. When source is available, use an ancestor or patch-equivalence check and inspect the final helper plus regression. When only binaries are available, require a vendor statement that names the containing Chromium revision or the CVE fix.
The CVE record and Chrome notice establish severity and product action. The landed commit establishes root cause and source repair. The AV1 specification establishes that the sequence fields and transitions are part of the format. These sources answer different questions and should not be collapsed into one citation. A product advisory cannot prove the exact field list; a source diff cannot prove which signed desktop package users received.
Linux distributions may rebuild Chromium and append their own package revision. Their security tracker or changelog can declare the CVE fixed even when the visible browser version does not exactly match Google's string. Administrators should use the distribution's fixed package evidence and confirm the active executable path. Mixing Google Chrome, distro Chromium, Flatpak, Snap, and application-bundled engines on one host creates several independent remediation units.
The fixed release line also sets a floor for triage. Any crash collected from an older build remains compatible with the vulnerable source path until provenance proves a backport. A crash from a fixed build does not automatically exclude a downstream integration error, a partial backport, or another media defect. Preserve revision and backend facts so the investigation can distinguish source state from symptoms.
The announcement also exposes a mundane inventory trap. Three-component normalization erases the distinction between the two packages named above, while a single maximum-patch rule rejects the Linux package Google actually shipped. Store the unshortened four-part string and evaluate it together with platform and channel.
Stable, Extended Stable, and enterprise-repackaged channels can publish on different schedules. The July 8 Stable notice establishes upstream product action, but it does not prove that a long-support device has already received its channel's package. Update rings, proxy caches, and relaunch deferrals can extend the interval, so channel-specific release evidence belongs in the asset record.
A multi-process restart must include the GPU process. Closing visible windows can leave background mode, extension hosts, or notification processes alive, and a subsequent window can reconnect to old mapped media code. Managed rollout should use the vendor-supported relaunch mechanism and verify that both browser and GPU-process start times postdate installation.
Vendor questionnaires should ask for the secure product version, release date, embedded Chromium revision, direct or equivalent patch status, required restart, and the component that owns AV1 hardware decode. A bare “not affected” answer cannot distinguish absent source, unreachable acceleration, completed remediation, or unfinished analysis.
For closed-source products, provenance can combine package manifests, module versions, symbol strings, vendor SBOMs, release notes, and support-case statements. Each clue can be incomplete. Closure needs a formal vendor mapping or another repeatable binary-to-revision proof that ties the running module to the corrected decoder.
Rollback directories require their own check. Updaters often retain the previous package for recovery; normal launch can use the fixed engine while a later rollback reactivates the vulnerable one. Product-supported policy should keep rollback above the security floor or invalidate the older package without corrupting updater state.
An SBOM entry that says only “Chromium 150” is too coarse. The major line contains snapshots on both sides of the fix, and vendors can cherry-pick media changes independently. Useful evidence records the outer product version, exact Chromium or media revision, patch provenance, and final artifact digest.
Offline devices still process media through USB, internal content distribution, maintenance tools, or test fixtures, and their update cadence is often slower. Their network isolation changes delivery opportunity but not decoder lifetime. Schedule them against actual media sources and hardware capability instead of waiting for browser auto-update.
Risk ordering can combine four dated facts: whether the product contains the vulnerable revision, whether it can select AV1 hardware decode, whether it accepts untrusted media, and whether a dependable rapid-update path exists. The first two establish technical reachability, the third affects trigger opportunity, and the fourth controls exposure duration. Prioritization can set rollout order, but it does not shrink the source population that requires correction.
Version evidence ultimately attaches to a runtime unit. For desktop software that unit is an executable and mapped module; for containers it is an image digest and instance; for services it is a deployment revision; for firmware it is a signed bundle and active slot; for browser-test caches it is a download key and launched binary. One host-level CVE state would erase the differences among those independent Chromium copies.
6.2 Reachability depended on the real hardware decode path
Source presence and runtime reachability form separate parts of exposure. The vulnerable code sits in Chromium's media/gpu AV1 decoder and matters when a product uses that decoder with an accelerated backend whose context resources depend on the changed sequence fields. A device with no AV1 hardware decode may fall back to software and never traverse the stale hardware context. It still needs the vendor update because capability, policy, driver, or workload can change.
Inventory begins with products that accept untrusted or externally supplied video. Browsers render media from websites. Collaboration clients preview messages and meeting streams. Content-review tools inspect uploads. Digital signs and kiosks fetch scheduled assets. Desktop shells can expose media through embedded web content. Automated test systems download arbitrary pages. Each surface can deliver an AV1 sequence transition without asking the user to open a standalone video player.
Hardware selection is dynamic. The same executable can choose different paths across GPU models, driver versions, remote desktop sessions, virtual machines, battery modes, sandbox settings, or enterprise policies. A laboratory system that reports software decode does not establish that a production kiosk with GPU pass-through behaves the same way. Record decoder selection in the workload's real session, along with GPU vendor and device identifiers, driver package, operating system, and relevant feature policy.
Chromium media diagnostics can show the selected decoder for a controlled benign AV1 sample. Product-specific logs or internal pages may expose whether decoding is hardware accelerated; if a product has no visible interface, its supplier can provide supported debug logs or a test build that observes accelerator construction. These checks should use known-safe media and aim only to establish route selection. Feeding an unknown crash sample to fleet devices would add operational risk and contaminate evidence. The source fix and package version remain the remediation criteria.
A global “hardware acceleration enabled” flag is too coarse for this inventory. The GPU may accelerate compositing while AV1 remains on a software decoder, and one AV1 profile, bit depth, resolution, or protected-content path can select a different backend from another. Route evidence should name the codec, profile, sample characteristics, selected decoder, and session in which the observation was made. That prevents a successful graphics check or unrelated H.264 playback from being reused as proof about AV1.
Driver updates can improve validation or make one symptom disappear, yet they do not complete the Chromium repair. The shared decoder would still decide that an incompatible context may be reused. Future hardware, another driver branch, or a newly exercised tool could expose the stale contract again. Update the driver according to vendor guidance when investigating GPU faults, but close the CVE only when the product's decoder contains the complete reset comparison.
Asset owners should record multiple engines inside one installation. An application updater, main UI, plugin host, crash reporter, and bundled test browser can ship different Chromium libraries. Old directories may remain for rollback. Map each executable to the module it actually loads and its source provenance. The display version in an uninstall registry or management console may describe the application package while saying nothing about a helper process launched from another directory.
Cloud and container workloads need the same rigor. Base images can install system Chromium; application layers can download a test browser; CI caches can retain snapshots; running containers can survive after a fixed image is published. Tie evidence to image digests, browser cache keys, deployment revisions, and container creation times. Rebuilding an image does not update already running instances.
File extensions, MIME labels, and outer containers are also weak routing evidence. A product can demultiplex AV1 from a familiar media container, receive an elementary stream from another component, or hand an uploaded asset through a thumbnailer before the main player sees it. Legal sequence switches can follow content splicing, a live encoder restart, or an internal transcode while the application continues to display the same nominal format. Inventory should observe the codec actually parsed, the sequence transition, and the backend selected at the point of decode; a catalog label or CDN filename cannot answer those questions.
If hardware decode is disabled during rollout, prove the route on each product after a full restart: the normal application session, child processes, embedded views, and any service launched with custom flags must all select software decode. Record CPU use, power draw, fan behavior, dropped frames, the accountable owner, the expiry, and the removal criterion—the corrected module active in the real process. This dated route record is the containment evidence; a settings-page toggle is not.
Some downstream packages identify the media component through a split repository and a GitOrigin revision. When that provenance model is in use, retain both the media-mirror identifier and its mapped Chromium commit. The pair prevents a package built from the corrected media tree from being misclassified solely because its manifest does not expose the outer Chromium hash.
7 The first useful evidence usually appeared in the GPU process
7.1 Crashes needed build, backend, and transition context
An incident rarely announces itself as CVE-2026-15114. The visible event may be a GPU-process termination, a decoder reset loop, a driver timeout, a protected-memory fault, a device-removal message, a frozen video surface, a renderer failure, or a browser tab that recovers after the graphics stack restarts. Those symptoms are common across hardware faults and media bugs. Their evidentiary value comes from correlation with a vulnerable build, accelerated AV1, and a sequence transition that changes one of the fifteen fields.
The relevant events can span processes and clocks. Chromium may parse in one component, own the accelerator in the GPU process, and call into an operating-system media service or firmware that reports the final fault elsewhere. Correlate configuration return, context construction, first submission, and device error with a privacy-safe session identifier, normalized timestamps, and the module revision for each process. A driver top frame alone is weak evidence, while a stable browser PID does not prove the GPU or media-service generation stayed alive.
Collect version facts before reproducing anything. Record the complete product version, executable path, package source, Chromium or media revision if exposed, process start time, operating system, GPU vendor and device IDs, and driver version. Capture policy and command-line switches that influence acceleration. On virtual or remote systems, record session type and pass-through state. These details determine which decoder and context implementation were present when the fault occurred.
Media-pipeline evidence supplies the next layer. Preserve the selected decoder name, codec profile, coded and visible dimensions, color configuration, configuration-change events, and GPU context identifiers where diagnostics expose them. If logs can safely include parsed sequence fields, record only the relevant old-to-new values and timestamps. This establishes whether an allocation-sensitive transition occurred and whether a new context appeared before the following submission.
Crash artifacts need the same timeline. A browser dump, GPU-process dump, operating-system event, driver reset report, and application log may use different clocks. Normalize them and retain original timestamps. The top stack frame can land in Chromium, a vendor user-mode driver, an operating-system media library, or a generic device-loss handler. Build and transition context give that stack meaning; the module name alone cannot identify the source defect.
If policy permits retaining the source media, calculate a cryptographic hash, store the original unchanged, document acquisition context, and restrict access. Do not circulate the file as a casual test clip. Investigators can first parse it in an isolated, non-production workflow to determine whether it contains multiple sequence headers and which high-level fields change. Any further reproduction should use the smallest authorized lab scope and the fixed unit test whenever it answers the question.
Absence of a dump is not proof of absence. GPU process recovery can discard volatile state, privacy controls can suppress media URLs, and firmware faults can surface only as a generic device reset. A cluster of similar events on the same vulnerable product, GPU family, and media object still deserves review. Conversely, a single driver timeout with no AV1 evidence does not justify attributing it to this CVE.
The public sources do not report confirmed in-the-wild exploitation. That statement bounds current evidence; it does not certify every historical crash as benign. Response teams can communicate the confirmed facts: a high-severity memory-safety defect existed in the hardware codec lifetime decision, Chrome shipped a fix, and public material does not establish a complete exploitation chain. Version remediation does not need to wait for exploit attribution.
Classify a fault by phase before interpreting its address. Failure before the new sequence header is accepted points toward syntax or transport handling. Failure during configuration can implicate teardown or allocation. Failure after sequence B submits on an unchanged generation matches the stale-context condition most closely. This phase model keeps unrelated AV1 problems from being folded into one crash bucket.
Production builds may not expose a context generation. In that case, combine the last configuration-change event, accelerator creation or destruction messages, decoder-selection logs, and first post-transition submission timestamp. A canary build with explicit generation instrumentation can establish how those proxy signals appear on each backend, giving production investigators a documented interpretation.
Two clustering directions answer different questions. One media hash faulting across many devices suggests content-linked delivery; many unrelated media hashes faulting on one GPU and driver combination suggests platform instability. A vulnerable build and the allocation-sensitive transition still need to join either cluster before this CVE becomes a strong explanation.
A fixed-build comparison should focus on the lifetime trace, not on recreating a fault. Parse the preserved sample in an isolated workflow, confirm the relevant sequence transition, and show the corrected build raises configuration and changes generation before submission. That result establishes the repaired causal chain even if allocator or driver differences prevent the old symptom from recurring.
7.2 Quiet telemetry could narrow a case without turning media into an exploit probe
Useful detection begins at low volume. Count configuration changes and hardware-context creations around AV1 sessions, keyed to a privacy-preserving session identifier. A coded video sequence that changes tool flags should produce a matching reconstruction event on fixed code. A transition followed by submission on the same context identifier is a direct invariant violation in test or canary telemetry and deserves immediate engineering attention.
Production telemetry may not expose all fifteen fields, and collecting raw media syntax at scale can create privacy and data-handling problems. A compact change bitmap, backend name, build ID, and context-generation counter can provide enough signal. The bitmap records which reset categories changed without retaining frame contents or URLs. Access controls and retention should match the organization's media telemetry policy.
Canary validation is a safer place for detailed traces. Instrument RequiresHardwareContextReset() to log the old and new field vectors, the Boolean result, and a monotonic context generation. Instrument the accelerator owner to log teardown and construction. Instrument submission to log only the generation. The expected sequence can then be asserted mechanically while controlled benign fixtures traverse each supported backend.
After deployment, compare pre-update and post-update fault rates, but do not use a quiet graph as the sole proof. The vulnerable transition may be rare, and many contexts over-allocate enough to avoid obvious failure. Package provenance, process restart, the upstream regression, and backend ordering tests provide deterministic evidence. Telemetry checks for missed assets and unexpected integration behavior.
8 Before the second frame crossed, the cabinet had to be rebuilt
8.1 Release proof joined source, package, process, and transition
Source verification starts with the complete predicate. Inspect the branch's equivalent of RequiresHardwareContextReset() and account for all fifteen fields. Confirm the caller evaluates it when an existing sequence header changes and includes the result in the condition that returns the configuration event. Trace the path far enough to show the return happens before picture creation or submission under the new header.
Run the chapter 4 transition regression in the candidate release configuration. Save the source revision, toolchain, build arguments, architecture, unabridged result, and candidate-test binary digest under the release identifier. Confirm both arrays parse into the expected equal conventional configuration and different tool state, and that both invocations produce kConfigChange followed by kRanOutOfStreamData.
For a downstream adaptation, inspect the test itself; a renamed green case supplies no equivalent proof. The second input must still bypass every conventional format trigger. The captured headers must still show equal maximum width, maximum height, profile, depth, chroma, and superblock choice. At least the intended allocation-sensitive values must differ. The mock or integration harness must prove decoding resumes and the second picture reaches a fresh context.
Backend validation instruments the ownership handoff. Assign a generation number when the platform context is created. Feed sequence A, allow its configuration event and decode cycle, then feed sequence B. Assert another event, destruction or retirement of the old generation, creation of a new generation, and submission only on the new generation. Repeat across GPU families and driver branches actually supported by the product.
Regression breadth should include normal behavior. Decode a stream with one stable sequence, a legitimate resolution change, identical consecutive sequence headers, film-grain transitions, and ordinary seek or flush operations. Confirm that reference clearing, output ordering, and resource counts remain correct. The patch changes a lifetime decision, so tests should detect both stale reuse and accidental reconstruction loops.
After source acceptance, follow every transformation from compilation through signing, stripping, application bundling, installer generation, and channel repackaging. The tested source, toolchain, build arguments, and binary digest must map to the signed package; then extract the decoder-bearing module from that package and confirm that clean installation and every materially different incremental path produce the same corrected artifact. An intermediate build result is not delivery proof.
The field worksheet records each target-branch member, comparison, and version guard, while three call-path checkpoints show the predicate becoming true, the combined condition returning kConfigChange, and the owner constructing a replacement accelerator. The focused log must show AV1DecoderTest.ConfigChangeOnSequenceHeaderToolFlags actually matched, ran, and passed rather than exiting successfully with zero tests. Backend tracing uses a monotonic generation so allocator reuse of the same object address cannot make a replacement look stale.
The canary matrix follows deployed share across principal GPUs, drivers, operating systems, and real VDI routes, recording decoder selection, generation transition, output, memory, and normal playback. Submission on the old generation is a security blocker; latency, dropped frames, or power cost after a legal rebuild is a performance defect to fix without weakening the predicate. Because ASan or UBSan may not see driver or firmware memory, GPU recovery can hide a software fallback, and repeated A→B→A cycles can leak resources, acceptance must test ordering, route, and resource counts separately.
An offline device, an embedded product awaiting a fixed package, or a canary playback regression can justify a release exception, but the record must name the asset, reason, security floor, next review, and restart condition. The item remains open until the corrected engine is installed and mapped by the process that actually owns decoding; the exception is not remediation.
The release record retains source, test, package, process, and generation evidence. If an asset is tied to a suspicious pre-update fault, link the chapter 7 fixed-build comparison instead of repeating the experiment. Closure requires the candidate to pass this chain, the authorized comparison to finish, and every remaining divergence to have a concrete next action.
8.2 The closing test returned to the same 720p scene
The final build record retains GN arguments, compiler and linker versions, architecture, feature flags, source, and dependency revisions, then re-extracts the decoder module from the signed package for comparison with the tested manifest. Clean installation and every materially different incremental path must produce the same module. A canary should also attempt one rollback and show that an unsafe target is rejected or corrected before launch, rather than merely checking a configuration value.
Runtime evidence comes from the process that actually owns decoding: the fixed package installs first, the old GPU process exits, a new process starts from that installation and maps the corrected module, and the benign transition completes on a new generation. A helper loading from a rollback, side-by-side, or user directory is not covered by the signed copy elsewhere on disk. Cross-host or container evidence also needs sequence identifiers or documented clock skew.
Source ancestry, field worksheet, test log, artifact digest, deployment record, process versions, and generation trace belong under one release identifier. Post-rollout monitoring finds missed restarts, unexpected fallback, and compatibility regressions; it does not replace deterministic repair proof. If later disclosure identifies a backend or buffer, the retained GPU/driver matrix and crash evidence support targeted reassessment. Closure requires a direct observation at every applicable layer and a concrete next action for every remaining gap.
- Build the asset ledger. List every product and executable carrying Chromium media code, then record the vendor release or source commit containing the fix, installation and process restart, actual AV1 hardware reachability, and the twin-sequence regression or supplier proof. Close an asset only when every applicable entry is complete.
- Patch the highest-exposure runtimes first. Begin with internet-facing and automatically rendered media surfaces, then cover internal, offline, and dedicated applications. Browser auto-update does not replace bundled engines, so search duplicate installations and rollback directories and require vendors to name the Chromium revision and context-reset coverage.
- Preserve the few volatile artifacts that matter. Where incident policy requires it, capture memory dumps and GPU logs from a small authorized set of suspicious pre-update devices before restart. Keep those held samples separate and continue broad deployment to the rest of the fleet.
- Restart and prove the live module changed. Replace browser, GPU, helper, kiosk, and container processes; verify the new process started after package installation and mapped the fixed module path or corrected image digest. Disk state alone is not closure.
- Exercise the safe transition. In controlled canaries, use a benign stream with the public regression semantics—unchanged 720p output, changed tool contract—and require a configuration reset plus a new context before submission. The check observes the lifetime handoff without attempting memory corruption or depending on a vulnerable driver.
Communication should state what the evidence supports. CVE-2026-15114 is a high-severity out-of-bounds read and write in Chromium Codecs caused by reuse of an AV1 hardware context across allocation-sensitive sequence changes. Chrome shipped fixed desktop builds on July 8. The public record does not provide a complete cross-platform exploit chain or confirmed active exploitation. The required action is still prompt update and restart across every affected Chromium runtime.
The engineering lesson extends beyond AV1. Image processors, neural accelerators, decompression engines, and cryptographic offload all need a complete compatibility contract whenever untrusted configuration creates persistent private state. Output equality cannot stand in for resource equality. Naming that internal contract, centralizing its invalidation, and testing transitions that hold public format steady while private requirements change turns a backend assumption into an auditable lifetime guarantee.
At the end of the story, the second frame looks exactly like the first from across the room. Its width is unchanged, its colors fit the same display, and the application still calls the stream 720p. The difference is behind the door: before the frame crosses into hardware, Chromium now notices the new set of tools, clears the old relationship, raises the configuration gate, and builds a cabinet large enough for the work. The frame stays ordinary because the lifetime decision is finally complete.
Research record
9Evidence, objects, and sources
The material below preserves the identifiers and references used in this report.
9.1Research objects
Products, actors, techniques, affected objects, and control points discussed in the report.
Chromium AV1 hardware decoder out-of-bounds read/write
Complete sequence-tool reset comparison
Extracted hardware-context reset helper with four initial fields
Fifteen allocation-sensitive sequence fields
Same format, changed tools, mandatory kConfigChange
Platform-specific July 8 desktop security release
9.2Event chronology
- Initial validation refactor landed
Sequence-header validation was reorganized around an explicit four-field hardware-context invalidation helper.
- Complete field comparison landed
Commit 48c725cd3ed1 added eleven missing checks and a binary regression.
- Chrome stable fix published
Chrome associated the Codecs issue with CVE-2026-15114.
- SOSEC source reconstruction completed
SOSEC reconciled parser, configuration, accelerator, test, product, and response paths against public primary sources.
9.3Sources and material
- Chrome stable security update, July 8, 2026https://chromereleases.googleblog.com/2026/07/stable-channel-update-for-desktop_01162222768.html
- CVE-2026-15114 recordhttps://www.cve.org/CVERecord?id=CVE-2026-15114
- Chromium fix 48c725cd3ed1https://chromium.googlesource.com/chromium/src/+/48c725cd3ed15bad33f5efad89103dd7cbc11be6
- Chromium review 8021903 and unit-test discussionhttps://chromium-review.googlesource.com/c/chromium/src/+/8021903
- Fixed AV1 decoder source at 48c725cd3ed1https://chromium.googlesource.com/chromium/src/+/48c725cd3ed15bad33f5efad89103dd7cbc11be6/media/gpu/av1_decoder.cc
- AV1 decoder regression source at 48c725cd3ed1https://chromium.googlesource.com/chromium/src/+/48c725cd3ed15bad33f5efad89103dd7cbc11be6/media/gpu/av1_decoder_unittest.cc
- Parent of the final Chromium fixhttps://chromium.googlesource.com/chromium/src/+/353326bb94b506c10d0ebe3e40f5b34cbf015ccf
- Earlier Chromium AV1 context-invalidation refactorhttps://chromium.googlesource.com/chromium/src/+/f77363617210dd46fb5b7f765c4da1af718a7393
- Chromium review 7912486 for the earlier refactorhttps://chromium-review.googlesource.com/c/chromium/src/+/7912486
- Parent of the earlier AV1 refactorhttps://chromium.googlesource.com/chromium/src/+/b4fe89207b09b04c195cce1919492feba57b008d
- AV1 bitstream and decoding process specificationhttps://aomediacodec.github.io/av1-spec/
- Chromium media GPU architecture and accelerator documentationhttps://chromium.googlesource.com/chromium/src/+/refs/heads/main/media/gpu/README.md
- Chromium media component documentationhttps://chromium.googlesource.com/chromium/src/+/refs/heads/main/media/README.md
- Official libgav1 repositoryhttps://chromium.googlesource.com/codecs/libgav1/