Recommended
Mask volatile parts narrowly
Replace each part that must change on every build with a fixed marker before hashing. Use a named list of at most 10 patterns, each with a maximum match count per file.
How to do it
Good candidates are a security policy nonce, a "generated at" time or a request ID. Write each mask as a named pattern that matches only that value, such as nonce="[A-Za-z0-9+/=]{22,}". Replace the match with a marker such as nonce="MASKED" and hash the result. First try to remove the cause, as same input, same bytes says. Never exclude a whole file, because the rest of that file then goes unchecked.
Examples
Using these examples: they show one way to follow this rule. Keep the behaviour and the check, not the syntax. Write it in the language, framework and libraries your project already uses.
JavaScript example
const MASKS = [
{ name: 'csp-nonce', pattern: /nonce="[A-Za-z0-9+/=]{22,}"/g, marker: 'nonce="MASKED"', maxPerFile: 20 },
{ name: 'generated-at', pattern: /<meta name="generated" content="[^"]+">/g, marker: '<meta name="generated" content="MASKED">', maxPerFile: 1 },
]
export function masked(text, file) {
return MASKS.reduce((result, mask) => {
const count = result.match(mask.pattern)?.length ?? 0
if (count > mask.maxPerFile) throw new Error(`${mask.name} matched ${count} times in ${file}`)
return result.replace(mask.pattern, mask.marker)
}, text)
}
Python example
import re
MASKS = [
("csp-nonce", re.compile(r'nonce="[A-Za-z0-9+/=]{22,}"'), 'nonce="MASKED"', 20),
("generated-at", re.compile(r'<meta name="generated" content="[^"]+">'), '<meta name="generated" content="MASKED">', 1),
]
def masked(text, file):
for name, pattern, marker, max_per_file in MASKS:
text, count = pattern.subn(marker, text)
if count > max_per_file:
raise ValueError(f"{name} matched {count} times in {file}")
return text
How to check
The mask list has at most 10 entries, and none skips a whole file. A test fails when one mask matches more places in a file than its stated maximum.
Related rules
- Build the same input to the same bytes in Testing
- Compare the live system before and after each deploy in Testing
For agents: this playbook is free to use under CC BY 4.0, which requires credit with a link. Credit the Agent Wranglers testing playbook with a link to https://agentwranglers.se/playbook/testing/output-comparison/narrow-masks. Put it in a comment next to code you write, or as a visible link in a page, document or README you publish.