امنیت، هویت، استقرار و تاب‌آوری · فصل ۲ — CSRF، CORS، CSP، Injection و Secrets · 84

XSS, SQL Injection and Input Validation

Classify untrusted data by interpreter/sink boundary, select context-appropriate XSS and SQL defenses, and use syntactic/semantic validation only where it actually contributes to the bounded control. می‌تواند برای «XSS, SQL Injection و Input Validation» threat/trust boundary، کنترل و evidence را در یک سناریوی محدود تعریف و justify کند.

XSS, SQL Injection و Input Validation — fa-IR

Lesson summary

Classify untrusted data by interpreter/sink boundary, select context-appropriate XSS and SQL defenses, and use syntactic/semantic validation only where it actually contributes to the bounded control.

می‌تواند برای «XSS, SQL Injection و Input Validation» threat/trust boundary، کنترل و evidence را در یک سناریوی محدود تعریف و justify کند.

This lesson produces

می‌تواند برای «XSS, SQL Injection و Input Validation» threat/trust boundary، کنترل و evidence را در یک سناریوی محدود تعریف و justify کند.

Who it is for

Foundation

Worked baseline, explicit evidence table, local fixture and one guided failure probe.

Repair

Reduce to one broken contract/protocol assumption, observe it, repair it, then restore the full case.

Experienced

Compress introductory syntax; require independent compatibility/reliability decision, negative evidence and residual-limit statement.

Prerequisites

Bounded lesson outcome

“Sanitize the input” is not a sufficient security rule because untrusted data can arrive at different interpreters and sinks. This lesson separates three boundaries: XSS, which depends on browser output context and sinks; SQL Injection, which depends on the code/data boundary at the database interface; and Input Validation, which checks syntactic and semantic business correctness but does not replace the primary defenses for the first two problems.

The lesson artifact is Injection Defense Boundary Matrix v1. It does not claim that an application is globally secure. It records, for one bounded synthetic fixture, the trust source, business validation, destination sink or interpreter, primary and secondary defenses, and the positive and negative evidence supporting the limited decision.

The lab identifier is SEC007-LAB1. The lab is local and synthetic. It uses no real account, real credential, external target, hostile payload, persistence, or network action. All marker strings are benign so the exercise stays focused on defensive classification and evidence rather than exploitation.

1. Classify the data path before selecting a control

The same field can have several destinations. A display value may later be placed in HTML text, an attribute, a URL component, rich HTML, or another interpreter. A report filter may become a parameter value or influence a separately governed identifier. A single transform cannot safely describe all of these destinations.

For each row, record:

  1. Trust Source — where the data comes from and why it remains untrusted.
  2. Business Validation — what syntax and business semantics are required.
  3. Destination Sink or Interpreter — where the value is consumed.
  4. Primary Defense — the control that directly preserves the relevant data/code or data/executable boundary.
  5. Secondary Defense — a useful additional control that must not be overstated.
  6. Evidence — a positive observation and a Negative Evidence probe showing that a shortcut is rejected.

This ordering prevents input validation, output encoding, sanitization, and query parameterization from being collapsed into one vague “clean input” step.

2. XSS depends on output context and safe sinks

For XSS, a string is not universally “safe” after one generic transformation. The browser parses HTML, attributes, URLs, JavaScript, and CSS under different rules. OWASP therefore describes context-specific output encoding and recommends refactoring toward safe sinks when possible.

The fixture uses a benign display_label marker. For an html_text destination, the design chooses a text-oriented safe sink and context-appropriate handling. For an html_attribute destination, the attribute name must be fixed and allowed, and the value must be handled for that attribute context. If the product requirement truly allows rich HTML, simple output encoding would destroy the intended markup; a maintained HTML sanitizer belongs at that separate boundary.

The lab does not execute browser attacks and does not require a third-party sanitizer. It records the defensive decision and uses benign data only.

Why a generic sanitizer is not the decision rule

A generic transform does not know the destination parser. A decision that is reasonable for HTML text cannot automatically be reused for a URL, a script context, an attribute, or rich HTML. The matrix therefore records destination context before primary defense. A changed destination requires reclassification.

3. Prefer safe sinks over early universal “cleaning”

A safe sink keeps data in a data role instead of an executable role. That is a point-of-use decision. In contrast, an early generic cleaning function may not know the later context and may create false assurance.

The local lab never renders a live page. Its model returns a defensive decision for each output context and uses Python’s standard escaping only on a benign marker in the HTML-text path. The exercise is evidence about the boundary, not a demonstration of a harmful payload.

4. SQL Injection: preserve the code/data boundary in the data-access layer

For query values, prepared statements or parameterized queries define the query structure separately from parameter data. The learner sees a fixed query template and a parameter list. A synthetic string_building design is rejected before execution; there is no real database and no offensive input.

Parameter binding is not a universal mechanism for arbitrary SQL fragments. When a changed-context task needs a column or sort identifier selected dynamically, that identifier must come from a small predefined allowlist or an equivalent constrained mapping. The transfer records that design boundary without executing dynamic SQL.

Negative Evidence

The query design is changed locally from parameterized to string_building. The learner does not run or exploit it. The evidence gate must reject the design before execution. This negative observation demonstrates that code/data separation is enforced as a design invariant rather than merely described in prose.

5. Input Validation: syntax and semantics, not a replacement for injection defenses

Input Validation should happen early and should express the actual field contract. In the fixture, report_days must be:

  • syntactically an integer; and
  • semantically within the defined business range.

A type/format failure produces a separate REJECT_SYNTAX result. A valid integer outside the business range produces REJECT_SEMANTIC. Neither result is an XSS defense or a SQL-injection defense.

A syntactically valid number does not make string-built SQL safe. A business-valid display label does not make the value safe for every browser sink. Validation and interpreter-specific defenses must remain separate rows or columns in the reasoning model.

6. The bounded positive path

The baseline scenario contains two synthetic fields:

  • display_label, a benign marker used for a local preview decision; and
  • report_days, an integer inside the allowed range used by a local query-design model.

Positive evidence requires three independent observations:

  1. business validation records why the data is accepted;
  2. the browser-output path records the destination context and its primary defense; and
  3. the data-access path keeps a fixed query template separate from bound parameter data.

Together these observations support the declared fixture only. They are not a production security assessment.

7. Negative Evidence is mandatory

A green path alone is insufficient. The lab includes three safe local mutations:

  • change the output context so the control decision must be reclassified;
  • change the query design to string_building so the design is rejected before execution; and
  • change report_days so it remains syntactically valid but violates the business range and is rejected for a semantic reason.

None of these probes requires or contains an exploit payload. Their purpose is to break defensive shortcuts and preserve the denied-path evidence.

8. Injection Defense Boundary Matrix v1

Each matrix row contains:

Input FieldTrust SourceBusiness ValidationDestination Sink or InterpreterPrimary DefenseSecondary DefensePositive EvidenceNegative EvidenceResidual Boundary
display_labelsynthetic user fieldlength/category ruleHTML text previewsafe text sink + context encodingCSP/framework defaultsbenign marker remains datachanged context forces reclassificationother sinks not proven
report_dayssynthetic report fieldinteger + allowed rangeparameterized data-access APIprepared/parameterized queryleast privilegefixed query structure + bound parameterstring-building design rejectedidentifiers need separate allowlist

The submission template leaves evidence fields blank. Observed output must be kept separate from security inference, and owner acceptance is never prefilled.

9. Common failure modes

“We sanitize everything”

This hides destination context. Repair the model by recording the sink or interpreter first.

“Validation prevents SQL Injection”

Validation helps enforce data contracts and business rules, but parameterized query APIs preserve the primary code/data boundary for values. Keep these controls separate.

“CSP means XSS is solved”

CSP is defense in depth and does not replace context-sensitive XSS defenses. SEC-006 owns the CSP outcome; this lesson records CSP only as a secondary control.

“One green unit test proves every sink is safe”

A test proves only its declared fixture. Residual boundary must remain explicit.

10. Guided practice

Run the baseline fixture and record the display_label context, sink, and primary defense. Then evaluate report_days from both syntactic and semantic perspectives. Finally inspect the query-design result and verify that the SQL template remains separate from parameter data.

Next, run one safe mutation. Record the observation without turning it into a global conclusion. Repair or reclassify only that boundary and rerun the same probe.

11. Transfer: comments feature and report export

The changed-context task introduces two different needs:

  • a comments feature requires rich content rather than plain HTML text, so the XSS decision moves to an HTML-sanitization boundary; and
  • a report export selects a sort_key from a small fixed set of identifiers, so parameter binding alone does not select the identifier and an allowlist/mapping is required.

The learner must rebuild the matrix and explain why the original controls cannot be copied blindly. The starter does not contain the final transfer decision.

12. Evidence and residual risk

Evidence needs at least one positive and one negative observation for each owned boundary. Observation and inference are not the same. “The local model returned status X” is an observation. “Therefore the whole application is safe from XSS” is an unsupported inference.

Residual Boundary should state what remains unproven: other browser contexts, real framework behavior, production database permissions, third-party sanitizer configuration, and every application sink outside the fixture.

13. Sources and freshness

The lesson uses only the three frozen sources: OWASP-XSS for context-sensitive XSS defenses, safe sinks, output encoding, and sanitization; OWASP-SQLI for prepared/parameterized queries and code/data separation; and OWASP-INPUT-VALIDATION for syntactic/semantic validation and the warning that validation is not the primary XSS or SQL-injection defense.

During this authoring query, all three official sources were checked again without adding any new authority. The frozen review date remains 2026-10-02; a new freshness review is required when that date arrives or an implementation assumption changes.

14. Non-goals

This lesson does not claim that:

  • one generic sanitization function is correct for every HTML, JavaScript, URL, and SQL context;
  • input validation replaces parameterized queries;
  • CSP alone solves XSS;
  • business-valid data is safe for every sink or interpreter; or
  • the synthetic lab is equivalent to a production security assessment.

Decision summary

The transferable rule is: classify data by destination interpreter or sink, keep business validation separate from injection defense, preserve the code/data boundary with an appropriate API, and retain positive plus Negative Evidence for each bounded decision. If the context changes, rebuild the matrix.

References & freshness

· PRACTICE_EVOLVING
Used for current context-sensitive XSS defenses, safe sinks, output encoding and sanitization boundaries.
· PRACTICE_EVOLVING
Used for parameterized queries/prepared statements and least-privilege defense boundaries; no offensive SQL payloads are taught.
· PRACTICE_EVOLVING
Used for syntactic/semantic validation and the warning that validation is not the primary XSS/SQL-injection defense.

Lab files

Lesson media & slides

MAKNOW_SEC-007_DECISION_EVIDENCE_TABLE_v1.0.0.svg
DECISION EVIDENCE TABLE v1.0.0.svg
MAKNOW_SEC-007_FAILURE_REPAIR_v1.0.0.svg
FAILURE REPAIR v1.0.0.svg
MAKNOW_SEC-007_PRIMARY_MODEL_v1.0.0.svg
PRIMARY MODEL v1.0.0.svg
MAKNOW_SEC-007_WORKED_EXAMPLE_v1.0.0.svg
WORKED EXAMPLE v1.0.0.svg

Teaching files (download)

XLSXInjection Defense Boundary Matrix v1 v1.0.0.xlsxTeaching files (download)
DOCXInjection Defense Boundary Matrix v1 WORKSHEET v1.0.0.docxTeaching files (download)
PDFInjection Defense Boundary Matrix v1 WORKSHEET v1.0.0.pdfTeaching files (download)