Commit Graph
6439 Commits
Author SHA1 Message Date
Matt Van Horn 08168e868f fix(audit): keep coverage unknown for an unread unclassified member
A packaged member with no format of its own, such as a PyInstaller
payload.bin, recorded only a skipped text member when its read failed
before the header. Member coverage then stayed complete, though the
member could be a native image or carry a nested package. Leave
coverage unknown and say which member could not be read, as an unread
native member already does.
2026-11-03 21:24:49 -08:00
Matt Van Horn 73b0522e6b fix(audit): keep a selected package executable's native carrier format
A directly selected PyInstaller executable named release.map recorded the
package format as its member format, even though its ELF or PE carrier was
already recognized. examineMember then missed the native-first branch and
treated the executable as a linker map, reporting a debug companion.
Forward the native carrier format for the selected file, as listed members
already do.
2026-11-03 21:14:42 -08:00
Matt Van Horn 615aef5d33 fix(audit): read Go's linker -r setting as a runtime search list
go tool link -r sets the ELF dynamic linker search path, dir1:dir2:...,
which the linker writes to RUNPATH. It was read as one whole path, so a
release built with -ldflags='-r=$ORIGIN/../lib' reported the
loader-relative entry as a build path and go.build_paths as exposed.
Read -r entry by entry with the same image-loader-aware split and token
filter a forwarded -rpath uses: ELF splits at ':' and drops $ORIGIN
entries; Mach-O keeps the argument as one directory.
2026-11-03 17:40:08 -08:00
Matt Van Horn 6d9efe6363 fix(audit): byte-check members whose kind is only an inventory path role
Inventory gives a packaged member a role from its name, such as resource
for payload.json or source-map for payload.map. The packaged-format guard
treated any kind other than "file" as owner-stated, so a nested ASAR an
ASAR lists under one of those names skipped signature recognition and
cleared coverage. Track whether the package owner stated the kind (Bun
sourcemap region, SEA main script) and only skip the byte check then.
2026-11-03 17:27:52 -08:00
Matt Van Horn f8c78d1302 fix(audit): keep a declared .map link beside a selected script a source map
The sibling scan counted any .map symlink as a skipped debug companion
before checking whether the selected script declared it as its source
map. classifySiblingMap already excludes a declared target that is a
regular file, so a declared symbols.map link added a false unknown to
debug_companions. Apply the declared-target check before either file-type
branch; noteUnreachedTargets still counts the unread map as skipped.
2026-11-03 15:46:37 -08:00
Matt Van Horn a592efd448 fix(audit): expand only the image loader's runtime tokens
A runtime search path token is expanded only by the loader of the image's
format. The ELF loader expands $ORIGIN, $LIB and $PLATFORM; dyld expands
@executable_path, @loader_path and @rpath. Each is literal text to the
other loader, so -Wl,-rpath,$ORIGIN:/opt/private-runtime on a Mach-O image
names a literal directory, yet it was dropped and go.build_paths reported
not_observed. Pick the token set from the native image format; the PE
loader reads no search list, so it expands none.
2026-11-03 15:41:59 -08:00
Matt Van Horn 4241d47986 fix(audit): split a linker search list only for an ELF image
Only the ELF linker reads a -rpath or -rpath-link argument as a
colon-separated list. The Mach-O linker stores each -rpath argument as one
directory, so -Wl,-rpath,@loader_path/lib:extra is a single loader-relative
entry, yet it was split and extra was reported as a build path. Carry the
native image format into the Go flag reader and split search lists only for
ELF; other formats read the whole argument as one entry.
2026-11-03 14:08:07 -08:00
Matt Van Horn 2cf0df1123 fix(audit): count a .map link beside a selected file as a skipped companion
The sibling scan skipped any .map entry that was not a regular file, so a
symlink such as symbols.map -> payload beside a selected executable left
debug companion coverage at not observed. The reader never follows links,
so the linker map such a link may name is unread, not absent. Count a
generic .map sibling link as a skipped companion without following it,
as noteUnfollowedMapLink already does inside a selected directory.
2026-11-03 14:05:08 -08:00
Matt Van Horn 198b1990a5 fix(audit): expand loader tokens only in a linker search list
The runtime loader expands $ORIGIN and @loader_path only in a -rpath or
-rpath-link search list. The token filter also ran on the argument of -T,
-L and -I, so -Wl,-T,$ORIGIN.ld dropped a literal linker script path and
a complete read could report go.build_paths as not observed. Search list
entries keep the filter; every other linker path argument is kept as is.
2026-11-03 13:59:23 -08:00
Matt Van Horn 0afcaea8ff fix(audit): read each entry of a forwarded linker search list
-rpath and -rpath-link take a colon-separated search list. The loader
token filter tested the whole list, so -Wl,-rpath,$ORIGIN:/opt/private-runtime
dropped /opt/private-runtime along with $ORIGIN, and the rooted-path pass
cannot see an entry that follows a colon. Split each search list into its
entries and drop only the loader-expanded ones.
2026-11-03 13:51:59 -08:00
Matt Van Horn a44e0e13ff fix(audit): read forwarded -rpath and -rpath-link as linker paths
A cgo build with CGO_LDFLAGS=-Wl,-rpath,private-runtime kept the
relative directory, but the forwarded linker parser only knew -L, -T,
-I, --library-path, --dynamic-linker and --script, so go.build_paths
reported not_observed. Add -rpath and -rpath-link to the same parser,
in the attached, = and next-field forms. Loader-expanded values such as
$ORIGIN/../lib and @loader_path/Frameworks name no build-host directory
and stay unreported.
2026-11-03 12:23:16 -08:00
Matt Van Horn 279254b7e7 fix(audit): route a selected native image named .map by its format
A directly selected or listed native image has no package format, so
examineMember skipped its native-first branch and sent a file such as
release.map through map routing. Its bytes then became a linker-map
guess and marked native.debug_companions exposed. Native format now
outranks the name for every member, packaged or not.
2026-11-03 12:08:57 -08:00
Matt Van Horn c38958683a fix(audit): read env settings after -- in a Node shebang 2026-11-03 10:38:06 -08:00
Matt Van Horn 65292aa84e fix(audit): count a dropped linker-map guess as a skipped companion 2026-11-03 10:34:45 -08:00
Matt Van Horn 0cb0d43e79 fix(audit): keep companion coverage unresolved for a generic .map link 2026-11-03 10:27:47 -08:00
Matt Van Horn 412f22ea78 fix(audit): skip env option arguments when reading a Node shebang 2026-11-03 10:13:38 -08:00
Matt Van Horn 02cd0e9360 fix(audit): keep a .map unsettled once a declaration was discarded 2026-11-03 10:07:39 -08:00
Matt Van Horn da5ecd81bd fix(audit): keep trimpath rewrites and directory fields apart from selectors 2026-11-03 08:40:54 -08:00
Matt Van Horn 3af7940d86 fix(audit): count an unread packaged member once 2026-11-03 08:36:41 -08:00
Matt Van Horn 87af4ef472 fix(audit): read rooted Go tool path arguments whole
`-L "/tmp/private,sdk"` and `-L=/tmp/a=b` name one directory, so a `,` or
`=` in a documented path flag's argument is literal. `-trimpath` keeps its
prefix=replacement structure.
2026-11-03 08:13:54 -08:00
Matt Van Horn 1d4853f073 fix(audit): keep coverage unknown for an unread packaged image
When a listed package member is a native image but its first read
fails, examinePackagedBinary returned before probePackagedImage could
mark its possible embedded package unexamined. Coverage stayed complete
and javascript.source_map_sources could report not_observed for a
payload nobody read.

Mark member coverage unknown wherever a native member goes unread,
including an encrypted one, as an image the probe could not read
already does, and say so in the limitations.
2026-11-02 21:52:24 -08:00
Matt Van Horn 728be11c9c fix(audit): keep a quoted Go argument whole
goFields already reads -L "/tmp/private - sdk" as two arguments, but
each field was then split again before every whitespace-led dash, so
go.build_paths reported /tmp/private instead of the retained directory.

Split again only a field that begins with a flag, after any package
selector, as a quoted "-L dir -s -w" does. Any other field is one
argument and is kept whole, in -ldflags, -extldflags and CGO flags.
2026-11-02 21:46:44 -08:00
Matt Van Horn ae0567435b fix(audit): read the Go linker's other path options
go.build_paths read only -L as a Go linker path option, so a retained
-ldflags='-tmpdir=private-obj -s -w' reported no path and --fail_on low
missed the directory.

Read every option `go tool link -h` documents as taking a directory,
path or file: -I, -L, -benchmarkprofile, -capturehostobjs, -cpuprofile,
-fipso, -importcfg, -memprofile, -o, -r and -tmpdir. -extld, -extar and
-libgcc name a program or `none`, so only their rooted values count.
2026-11-02 21:44:43 -08:00
Matt Van Horn e10f393034 fix(audit): read -extldflags paths as the external linker splits them
With -ldflags set to -extldflags '-L "/srv/private sdk"', the outer
flag reader could not match the path behind the inner quote, and the
external reader kept only relative paths, so go.build_paths read
not_observed. Read each -extldflags value once, as go tool link splits
it with quoted.Split, and collect rooted and relative paths from those
same arguments. The rest of the setting is read as before.
2026-11-02 21:38:13 -08:00
Matt Van Horn e1710a0516 fix(audit): read a retained -pgo setting as one profile path
`-pgo file` names a single profile, and under -trimpath Go keeps only
its file name, so the flag readers dropped values such as
`private-training.pgo` and split paths with spaces or commas. Report
the value whole, skipping `auto` and `off`.
2026-11-02 20:34:06 -08:00
Matt Van Horn 5d8627c80c fix(audit): keep a named script beside a selected HTML file unknown
A script element whose target had a JavaScript name such as app.js was
dropped on the assumption that it would be examined as a member. When
the selection is an HTML file, sibling scripts are never read, so a
sibling holding an inline map left javascript.source_map_sources
not_observed while the same target named app left it unknown. Record
every local script target so an unreached one counts as skipped.
2026-11-02 20:29:34 -08:00
Matt Van Horn 4c3d64fcd8 fix(audit): split Go flags as Go does and read external linker flags
Go splits a flag value with quoted.Split: a field that starts with a
quote runs to the matching quote, and any other quote is a literal
character. The reader stripped every quote, so CGO_CFLAGS
-I"/home/O'Neil/include" reported /home/ONeil/include, while cc was
given the directory "/home/O'Neil/include", quotes included.

-ldflags kept -extldflags values with the Go linker flags, where only
-L counts, so -extldflags=-Lprivate-sdk reported no path. The values
are now read as the C compiler driver reads them, including -Wl, and
-Xlinker forwarding.

A package member named payload.json or payload.js.map that holds an
ASAR took the text or map route, which checked only native signatures,
so the nested archive was scanned as text and coverage read complete.
The route's own read now recognizes the ASAR signature as well, and the
nested package leaves coverage unknown.
2026-11-02 20:21:34 -08:00
Matt Van Horn 5dfcb4120a fix(audit): read forwarded linker options by their linker meaning
The forwarded linker flag pattern read -Ttext=0x400000 as a script path
named text=0x400000, and it ignored -I, so -Xlinker -Ilib/ld-custom.so
lost the interpreter path the compiler flag pattern found before the
split.

Exclude the -T section and segment address options (bss, data, text,
text-segment, rodata-segment, ldata-segment) and read -I and
--dynamic-linker as paths.
2026-11-02 20:06:33 -08:00
Matt Van Horn 93beb67216 fix(audit): read paths a C compiler forwards to the linker
CGO flags can hand linker options through -Wl,a,b or -Xlinker a. The
compiler flag parser saw -Wl,-L,private-sdk as one field and missed the
relative library directory, so go.build_paths reported not_observed.

Split forwarded options out before reading paths and read them with the
linker's own path options (-L, -T, --library-path, --script). This also
stops -Xlinker -Bsymbolic from being read as the compiler's -B prefix.
2026-11-02 19:45:23 -08:00
Matt Van Horn 03bfcf76bb fix(audit): keep a declared JavaScript map beside a selected file unknown
A local sourceMappingURL with a JavaScript map name such as app.js.map
was dropped on the assumption that it would be examined as a member.
When the selection is a file, sibling .js.map files are never read, so
the declared map left javascript.source_map_sources not_observed while
the same target spelled as a file: URL left it unknown. Record every
local target so an unreached one counts as skipped.
2026-11-02 19:36:59 -08:00
Matt Van Horn 1354f58b50 fix(audit): keep map coverage unknown for a linked script
A link named app.js to an extensionless payload was skipped as a link,
and its target was read as plain text with no map directives parsed. An
inline map there left no parsed or skipped count, so
javascript.source_map_sources read not_observed. Only links with a map
name were counted.

Count a link under any name that can declare a map, the set an unread
member already uses. It stays one omission when a page or a directive
also names it. The target is still not followed.
2026-11-02 17:25:06 -08:00
Matt Van Horn 68fe35867c fix(audit): name a symlinked sibling debug companion
Selecting an executable skipped every symlink beside it before the name
check, so an app.pdb link left no companion path and no skip count, and
native.debug_companions read not_observed. Selecting the directory
reports the same link.

Check the name first. The map branch already needs a regular file, so no
link is followed.
2026-11-02 17:14:31 -08:00
Matt Van Horn 9fdb191d2c fix(audit): let a map or script read identify a native member
A package lists names without formats, so a PE called payload.js.map
took the map route and never reached a native probe. Its CodeView path
was lost, and with nothing counted as failed, native.pdb_path could read
not_applicable. A PE at a declared script or map target was lost the same
way, because declaration overrode the route.

Decide from the bytes the route already read, in the map route as in the
text route, and keep the listed kind for a promoted script target. Real
text and maps cost no extra read, so those allowances are unchanged.
2026-11-02 12:04:35 -08:00
Matt Van Horn 95e9531c2a fix(audit): read a text-named native member by its bytes
A PE member called payload.json took the text route, so it reached no
native probe, and its CodeView path and packaged-native uncertainty were
lost.

Decide from the bytes the text read already loaded, so real text costs
no extra read and the map and text allowances stay as they were.
2026-11-02 10:04:18 -08:00
Matt Van Horn 5d45f63f1c fix(audit): keep every possible host when no name picks one out
With no named Electron host, every sibling ranks alike and
electron_host_paths stayed empty, so one image's safe fuses settled the
checks even when another possible host reported none.

Keep all sampled candidates as hosts in that case, so a candidate
without fuses leaves the checks unknown.
2026-11-02 09:59:25 -08:00
Matt Van Horn 569589aac5 fix(audit): read the scripts of a standalone SVG
An SVG can carry a script with an inline source map, but only .html and
.htm members reached the script owner, so such a file left every map
counter at zero and javascript.source_map_sources read not_observed.

Treat .svg as a script-bearing page. htmlArtifactReferences already
reads SVG script elements, so this adds no parsing.
2026-11-02 09:57:06 -08:00
Matt Van Horn b9d820639c fix(audit): keep coverage unknown for a PE header past the probe
A packaged member whose PE signature lies beyond the probe prefix stayed
unclassified, so the embedded-package probe never ran and coverage stayed
complete. A map inside such an image then read as not_observed.

Record the member as an unexamined package where it is already marked as
a possible native image.
2026-11-02 09:54:22 -08:00
Matt Van Horn a37b652388 fix(audit): keep undecodable Go and Rust metadata unknown
Unsupported meant two things: a container this reader does not handle,
and metadata the image holds in a form the reader cannot decode, such as
a compressed .dep-v0 section. Both read as not_applicable, so an image
that carries metadata reported that the check did not apply.

Mark the second case on the format failure and carry it on
AnalysisUnsupportedTargetError, so the audit records a failed read and
stays unknown. The tools' own errors and messages do not change.
2026-11-02 09:51:50 -08:00
Matt Van Horn c0be177581 fix(audit): keep a declared sibling map out of the linker guess
When the selected file declared a sibling map, the sibling classifier
never consulted the declaration. A malformed assets.map then read as a
linker map and raised native.debug_companions.

Leave a declared sibling to the unreached-target accounting, as members
already are, so it stays an unresolved source map.
2026-11-02 09:47:55 -08:00
Matt Van Horn 175398565b docs(audit): say how go.build_paths treats rooted -X values
A rooted -X value cannot be told from a file path, so the audit reports
it. State that, and why, so the rule is a contract rather than a side
effect of how flags are scanned.
2026-11-02 09:45:43 -08:00
Matt Van Horn c5198d0d04 docs(audit): state the packaged image read allowance
Packaged ELF, Mach-O and PE images are read in full and copied to a
temporary file, sharing one max_file_bytes allowance, but the docs and
coverage.allowances still said only a PE gets more than a header read.

Name the allowance and the copies in docs/release-exposure.md,
RELEASE_EXPOSURE_ALLOWANCES and the max_file_bytes description.
2026-11-02 09:42:53 -08:00
Matt Van Horn 130a58cdbb fix(audit): read relative paths in Go compiler and assembler flags
A binary built with -gcflags=-I private-sdk keeps that setting, but
relative parsing covered only C compiler settings and -ldflags, so the
directory dropped out of go.build_paths.

Give -gcflags and -asmflags their own path options, taken from what
go tool compile and go tool asm document, and strip the package selector
as -ldflags does. The assembler's -D defines a symbol, so it is not one.
2026-11-02 09:40:24 -08:00
Matt Van Horn 56735007be fix(audit): record an unfollowed map link as skipped
The directory and ASAR readers do not follow links, so a symlinked
app.js.map dropped out before any map counter moved. Its target was
scanned as plain text, and both source-map checks read not_observed.

Count a link that names a map as skipped wherever entries reach the
audit, and mark it examined so a declaration does not count it twice.
2026-11-02 09:25:55 -08:00
Matt Van Horn 1ccbbf2fc7 fix(audit): retract only guessed linker maps on a declaration
A script declaring sourceMappingURL=symbols.pdb after the scan reached
symbols.pdb removed the shipped PDB from the companion list, because a
late declaration retracted any companion. native.debug_companions could
then read not_observed.

Keep name-identified companions in their own set, and retract only maps
that were read as non-JSON and guessed to be linker maps.
2026-11-02 09:12:13 -08:00
Matt Van Horn f9240a6414 fix(audit): match companions by member identity, not spelling
An ASAR member's location is relative, and a declared map target is
absolute, so a malformed assets.map read before z.js stayed a linker
companion. The examined-map lookup, which is normalized, then returned
early, leaving both source-map checks not_observed.

Index companions by memberLocationKey and keep each reported spelling
under it. Spellings stay distinct because symlinks can make them differ.
2026-11-02 08:59:15 -08:00
Matt Van Horn ffbba64510 test(audit): rethrow typed errors from release exposure checks
A failed Result was rewrapped in a plain Error, which dropped its type,
cause and cleanup details from the test output.
2026-11-02 08:09:11 -08:00
Matt Van Horn a1919fe276 fix(audit): keep a declared .map from reading as a linker map
A script's sourceMappingURL=assets.map was dropped because the name
already looked like a map. A malformed assets.map then settled as a
linker map, so both source-map checks read not_observed and
native.debug_companions reported an exposure the release does not ship.

Keep a generic .map name as a declared target and read it as a
JavaScript map, in either scan order, so it stays unresolved.
2026-11-02 08:04:45 -08:00
Matt Van Horn 3d0283dc21 fix(audit): keep a failed probe directory removal owned
A packaged image's probe copies the member's full bytes into a temporary
directory. When removing it failed, the error became an ordinary
unreadable probe: the audit could still succeed, nothing could retry the
removal, and the client heard nothing about the leftover bytes.

Hold the directory in the reader's resource scope, so close retries it,
and report the unfinished cleanup without replacing a primary failure.
2026-11-02 08:01:23 -08:00
Matt Van Horn 39e279448b fix(audit): keep linker strings out of Go build paths
Reading `-X 'main.usage=-L level'` as a library directory made
go.build_paths report `level`, so a plain string could fail an audit
under --fail_on low.

Read the optional package selector once, before the setting's first
flag, and keep the argument of -X attached to it, so a string it sets
is never scanned as another option.
2026-11-02 07:28:50 -08:00
Matt Van Horn a7f3b6a835 fix(audit): read a Node shebang as script identity
The path classifier gives an extensionless executable a resource kind,
so a script such as bin/runner with a `#!/usr/bin/env node` header was
scanned as text without its inline maps being examined or counted. A
complete inventory then reported no shipped sources for it.

The probe holds the first bytes a member reader sees, so establish the
identity there. The script keeps the usual outcomes: a map that is read
counts, and one past an allowance or undecodable stays unknown.
2026-11-02 07:21:21 -08:00