Safeguard
Application Security•

ASVS 5.0 V1.3.3: Sanitize Data Before Dangerous Contexts

ASVS V1.3.3 requires sanitizing data headed for dangerous contexts: allow only safe characters and cap length. See an allowlist helper and how to test it.

Safeguard Security Team
3 min read

ASVS 5.0 V1.3.3 (Level 2) requires that data passed to a potentially dangerous context is sanitized first to enforce safety rules, for example by permitting only characters that are safe for that context and trimming input that is too long. It covers sinks that other rules do not name, such as log lines, file names, shell like config values and downstream protocols.

Why it matters

Every sink has some input it cannot handle. A file name with ../ escapes a folder. A log line with a line break forges extra entries. A header value with a null byte is cut short by a C library. An oversized value exhausts memory or breaks a fixed width field downstream. Allowlisting safe characters and limiting length removes whole classes of surprises at once.

How to implement it

Define for each dangerous sink what is acceptable, write that down as a pattern and a maximum length, and apply it right before the call.

import re

SAFE_FILENAME = re.compile(r"[A-Za-z0-9._-]{1,100}")

def safe_filename(name: str) -> str:
    base = name.replace("\\", "/").split("/")[-1]
    if not SAFE_FILENAME.fullmatch(base) or base in {".", ".."}:
        raise ValueError("unacceptable file name")
    return base

def safe_log_value(v: str, limit: int = 200) -> str:
    return v[:limit].replace("\r", "\\r").replace("\n", "\\n")

Allowlists beat blocklists: you list what is allowed, so unknown tricks are rejected by default. Use fullmatch so a pattern cannot match only a prefix. If a value does not fit, reject it, and only rewrite values when rewriting is harmless for that context.

How to test it

Feed each sink long values (10,000 characters), control characters, Unicode lookalikes, null bytes and path separators. Verify rejection or safe handling, and check that log files never contain an unescaped line break from user data.

Common mistakes

  • Removing bad characters and passing along whatever is left, which can create new dangerous strings.
  • Checking length in characters when the sink limit is in bytes.
  • Sanitizing for one sink and reusing the value for another.

Where this goes wrong in practice

Log forging is the clearest example. An attacker submits a username like bob\nINFO login ok user=admin, and the log file now contains a convincing fake entry. Incident responders then trust a line that an attacker wrote. Escaping line breaks in user supplied log values, and cutting them to a sane length, costs one function call.

File names are the next common case. Uploaded names flow into storage paths, response headers and shell scripts that process the file later. A single allowlisted pattern for names, with a generated internal name for storage, closes most of the problems at once. Keep the original name only as display data and encode it for output.

Length limits matter for the sinks that have hard limits, such as fixed width columns, message queues and third party APIs. Decide the limit per field, enforce it at the boundary and measure it in bytes where the sink does.

Quick check

Why prefer allowlists?

A blocklist only stops what you thought of. An allowlist rejects everything you did not explicitly approve.

Sources

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.