Fixing an override in package.json and then triggering a rescan from the security page keeps reporting the old override set for up to an hour.
Cause
runOverrideAudit (src/lib/security/override-audit.ts:119) is cache-aware and accepts { force }:
if (!opts.force) {
const cached = readJsonCache<OverrideAuditOutput>("override-audit", project.id, cveLiteToolVersion());
if (cached) return cached;
}
But the scan source never passes it — src/lib/security/sources/override-hygiene.ts:81:
const report = await runOverrideAudit(project);
Two other callers do (overrides/[id]/route.ts:20, overrides/[id]/fix/route.ts:100), so the capability exists and is simply unused on the main scan path.
Invalidation in json-cache.ts is cachedAt + ttlMs (1h) plus toolVersion. Nothing consults the mtime or content of package.json or the lock file, so an edit to the very input the audit is about does not invalidate its cache.
Observed
do868.com — removed a stranded hono override at 11:39:54.
- cache
override-audit-do868-com.json written 11:31:52, ttlMs: 3600000
POST /api/projects/do868-com/security-scan at 11:51:36 → still reported OA001 and OA002 for hono, quoting the removed range >=4.12.25 <5
- the merged result
security-do868-com.json was rewritten at 11:51 from the stale payload, so the timestamp looked current while the content was not
- deleting the cache file and rescanning → hono findings gone, correct results
The failure mode is quiet: the scan reports success with a fresh timestamp, so there is no signal that a source was served from cache.
Suggested fix
Either (or both):
- Have an explicit user-triggered scan pass
force: true down to every source — a manual rescan should mean "actually rescan".
- Include the mtime/hash of
package.json and the lock file in the cache key, so editing the audited input invalidates the entry regardless of TTL.
Option 2 is the more complete fix; option 1 alone still leaves scheduled scans serving stale data for an hour after an edit.
Worth also surfacing per-source cache provenance in the scan result (fromCache: true + cachedAt), so a cached source is visible rather than indistinguishable from a fresh one.
Related
Found while verifying DO868/do868.com#39.
Fixing an override in
package.jsonand then triggering a rescan from the security page keeps reporting the old override set for up to an hour.Cause
runOverrideAudit(src/lib/security/override-audit.ts:119) is cache-aware and accepts{ force }:But the scan source never passes it — src/lib/security/sources/override-hygiene.ts:81:
Two other callers do (
overrides/[id]/route.ts:20,overrides/[id]/fix/route.ts:100), so the capability exists and is simply unused on the main scan path.Invalidation in
json-cache.tsiscachedAt + ttlMs(1h) plustoolVersion. Nothing consults the mtime or content ofpackage.jsonor the lock file, so an edit to the very input the audit is about does not invalidate its cache.Observed
do868.com— removed a strandedhonooverride at 11:39:54.override-audit-do868-com.jsonwritten 11:31:52,ttlMs: 3600000POST /api/projects/do868-com/security-scanat 11:51:36 → still reportedOA001andOA002forhono, quoting the removed range>=4.12.25 <5security-do868-com.jsonwas rewritten at 11:51 from the stale payload, so the timestamp looked current while the content was notThe failure mode is quiet: the scan reports success with a fresh timestamp, so there is no signal that a source was served from cache.
Suggested fix
Either (or both):
force: truedown to every source — a manual rescan should mean "actually rescan".package.jsonand the lock file in the cache key, so editing the audited input invalidates the entry regardless of TTL.Option 2 is the more complete fix; option 1 alone still leaves scheduled scans serving stale data for an hour after an edit.
Worth also surfacing per-source cache provenance in the scan result (
fromCache: true+cachedAt), so a cached source is visible rather than indistinguishable from a fresh one.Related
Found while verifying DO868/do868.com#39.