When to Use
Use this skill when auditing or hardening trading infrastructure — order routers, market data gateways, execution engines, trade databases, colocated hosts — for a financial institution regulated by the Monetary Authority of Singapore.
Start by getting the notice number right, because the most common error here is citing one that does not bind you. There is no single "MAS Notice on Cyber Hygiene." MAS issues the same six requirements as a separate Notice to each class of financial institution. On 10 May 2024 the earlier class notices (Notice 655 for banks, Notice CMG-N03 for capital markets entities, PSN06, TCA-N06 and others) were cancelled and reissued under the Financial Services and Markets Act 2022:
FSM-N22— capital markets financial institutions, the successor to CMG-N03. A trading firm holding a Capital Markets Services licence sits here.FSM-N06— banks in Singapore, the successor to Notice 655.
The requirements are identical; the notice number in your audit file is not. The engine makes the caller declare its entity_class and stamps the applicable notice on every report.
The six requirements, all mandatory, are (paragraph numbers as originally issued):
| Para | Requirement | Scope qualifier |
|---|---|---|
| 4.1 | Every administrative account on any OS, database, application, security appliance or network device is secured against unauthorised access or use | Every system |
| 4.2 | (a) Security patches applied within a timeframe commensurate with the risk each vulnerability poses; (b) where no patch is available, controls instituted to reduce the risk | Every system |
| 4.3 | (a) A written set of security standards for every system; (b) every system conforms; (c) where a system cannot conform, controls instituted | Every system |
| 4.4 | Controls at the network perimeter restricting all unauthorised network traffic | Every system |
| 4.5 | One or more malware protection measures, where such measures are available and can be implemented | Every system, qualified |
| 4.6 | Multi-factor authentication for (a) all administrative accounts on a critical system; and (b) all accounts on any system used to access customer information through the internet | Scoped — not universal |
When NOT to Use
- As evidence that a control is in place. The engine reads booleans the caller supplies. A clean report attests a control; it does not observe a host. Pair it with configuration scanning and the firm's own evidence collection.
- As a source of patching deadlines. The Notice fixes no number and neither does this skill.
PatchRemediationPolicyis deliberately mandatory and has no default, because a default here would be a fabricated regulatory threshold. - For requirements outside the Notice. Incident notification, technology risk management, outsourcing and business continuity live in the separate TRM Notices and the MAS TRM Guidelines. The Cyber Hygiene Notice is a six-requirement baseline, not the whole MAS technology framework.
- For per-order trading controls. Approved Trader registration, pre-execution value limits, the Forced Order Range and the SGX-ST circuit breaker are per-order gates — see
mas-singapore-algo-trading-guidelines. - Outside Singapore. These are MAS notices. The 4.6(a) "critical system" scoping and the 4.5 availability carve-out are Singapore drafting; do not carry them into a UK FCA or EU DORA assessment.
Prerequisites
- Which notice binds the entity:
entity_classof"CAPITAL_MARKETS"(→ FSM-N22) or"BANK"(→ FSM-N06). - The firm's own risk-commensurate patching deadlines (
PatchRemediationPolicy: max_days_by_severity). MAS publishes none — this is the firm's articulation of para 4.2(a). - Per asset, a
TradingSystemAssetcarrying:system_id,system_name,asset_type; the two scope determinantsis_critical_systemandaccesses_customer_information_over_internet; and the control attestationsadministrative_accounts_secured,open_vulnerabilities,has_written_security_standards,conforms_to_security_standards,nonconformity_controls_in_place,network_perimeter_controls_implemented,malware_protection_implemented,malware_protection_unavailable_justification,mfa_on_administrative_accounts,mfa_on_customer_information_accounts. - Per open vulnerability, an
OpenVulnerability:vulnerability_id,severity,days_since_patch_released(Nonemeans no patch is available, which moves it from 4.2(a) to 4.2(b)),compensating_controls_in_place. - A criticality determination for each asset: a critical system is one whose failure will cause significant disruption to the entity's operations or materially impact its service to customers.
Workflow
- Reject structurally invalid input before auditing anything. Blank identifiers, an unknown severity label, a negative
days_since_patch_released(it would compare below every deadline and pass silently), a boolean age (Trueis anintin Python and reads as 1 day), a mutable list of vulnerabilities, or duplicate vulnerability IDs all raise. These are caller bugs; reporting them as a clean audit would be worse than failing. - Fix the notice. Resolve
entity_classto its notice number and stamp it on the report. Auditing a CMS licensee against "FSM-N06" produces a compliance file that cites the wrong instrument. - Administrative accounts (4.1). Not attested as secured $\implies$ breach. Grant on a need-to-use basis; the requirement covers the OS, database, application, security appliance and network device layers, not just the OS.
- Security patches (4.2) — split the two limbs, they are not interchangeable.
- A patch exists (
days_since_patch_releasedis an int): compare against the firm's deadline for that severity. The deadline is inclusive — "within 7 days" is met at exactly 7. Over it $\implies$ breach of 4.2(a). Compensating controls do not excuse this; 4.2(b) is the answer to "no patch exists", not to "we did not apply one". - No patch is available (
None): controls must be instituted to reduce the risk $\implies$ else breach of 4.2(b). With controls recorded, the asset is compliant and the exception is carried as a warning to be re-tested when a patch ships. - A severity the policy does not cover raises rather than passing an unmeasured vulnerability.
- A patch exists (
- Security standards (4.3) — three limbs. No written standards $\implies$ breach of 4.3(a), and stop: conformance under 4.3(b) is unevaluable when there is nothing to conform to. Standards exist but the asset does not conform: with controls instituted $\implies$ compliant with a 4.3(c) warning; without $\implies$ breach of 4.3(b).
- Network perimeter defence (4.4). No perimeter controls $\implies$ breach. The requirement follows the traffic, including traffic reaching the asset through third-party or overseas-hosted networks.
- Malware protection (4.5) — honour the carve-out. Not implemented, with a recorded justification that measures are unavailable or cannot be implemented (a sealed vendor appliance, an FPGA feed handler) $\implies$ compliant with a warning. Not implemented with no justification, or a blank one $\implies$ breach.
- Multi-factor authentication (4.6) — scope it, do not universalise it.
- Limb (a) applies only to critical systems, and reaches administrative accounts.
- Limb (b) applies to any system used to access customer information through the internet, and reaches all accounts on it, not just administrative ones. A non-critical system can be squarely in scope through this limb alone.
- Neither limb applies $\implies$ the requirement is reported as not applicable, not as passed.
- Unknown scope (
None) resolves conservatively to in scope, with a warning, so an absent field can never make a breaching asset look compliant.
- Report. Every requirement is evaluated; nothing short-circuits. Output a
MASCyberHygieneAuditReportcarrying the fullbreachestuple (each pinned to its Notice paragraph),warnings, deduplicatedmandatory_remediations, andremediation_progress_pctmeasured over the applicable requirements only.is_compliantis the only figure with regulatory meaning.
Full procedure: see
references/workflows.md. Standards reference: seereferences/standards.md. Printable pre-flight checklist: seeassets/checklist.md.
Common Pitfalls
- Shipping a "30-day MAS patching SLA". No such requirement exists. Para 4.2(a) requires a timeframe commensurate with the risks posed by each vulnerability, and the MAS TRM Guidelines say the same in guidance form. A flat 30 days is wrong in both directions: far too slow for an actively exploited RCE on an order gateway, and an invented obligation for a low-severity issue on an isolated host. Worse, presenting it as a MAS figure means nobody ever calibrates it.
- Treating compensating controls as a patching amnesty. Para 4.2(b) applies where no security patch is available. An available patch left unapplied past the firm's deadline is a breach of 4.2(a) regardless of what controls sit around it.
- Applying MFA universally. Limb 4.6(a) is scoped to critical systems. A gate that demands MFA on every administrative account everywhere raises findings the Notice never raised, and firms learn to dismiss them.
- Ignoring MFA limb 4.6(b). A non-critical, internet-facing system that accesses customer information needs MFA on all its accounts. Auditing admin MFA alone passes exactly the asset most likely to be phished.
- Citing FSM-N06 at a capital markets firm. FSM-N06 is the banks' notice. A CMS licensee is under FSM-N22. Both replaced their predecessors on 10 May 2024, so citing Notice 655 or CMG-N03 cites a cancelled instrument.
- Presenting CIS benchmarks as the MAS requirement. Para 4.3 requires that a written set of security standards exist and be conformed to. CIS Benchmarks are a good basis for authoring one; they are not what the Notice mandates.
- Failing an asset that legitimately cannot run malware protection. Para 4.5 is qualified "where such measures are available and can be implemented". A sealed appliance with a recorded justification is compliant. Silently passing it without recording the justification, however, loses the audit trail for the exception.
- Reading the percentage as a compliance grade. Every requirement is mandatory: one breach means non-compliant. An asset at "83%" is not "mostly compliant".
remediation_progress_pctis an internal tracking figure over the applicable requirements, and it divides by the applicable count — not a flat 6 — so an asset the MFA requirement never reached is not marked down for it. - Defaulting scope flags to permissive values. Every control flag on
TradingSystemAssetdefaults to the non-compliant value, and unknown criticality resolves to critical. A partially onboarded asset must fail closed, not pass by omission. - Stopping at the first breach. An asset can breach 4.1, both limbs of 4.2 and both limbs of 4.6 at once. Remediation needs the full list.
Verification
- Instantiate
SingaporeMASCyberHygieneEngine(PatchRemediationPolicy(max_days_by_severity={"CRITICAL": 7, "HIGH": 14, "MEDIUM": 60, "LOW": 180})). Audit a fully compliant critical order router $\implies$is_compliant is True,breaches == (),remediation_progress_pct == 100.0,entity_notice == "FSM-N22". The same engine withentity_class="BANK"$\implies$entity_notice == "FSM-N06". - Confirm no 30-day rule survives: a
CRITICALvulnerability open 20 days must breach4.2(a)against the 7-day firm policy, while aLOWvulnerability open 90 days must pass against the 180-day policy. Both outcomes invert under a flat 30-day SLA. - Confirm the deadline is inclusive:
days_since_patch_released=7against a 7-day policy passes;8breaches. - Confirm the patch limbs are distinct:
days_since_patch_released=Nonewithcompensating_controls_in_place=True$\implies$ compliant with a4.2(b)warning; the same with no controls $\implies$4.2(b)breach;days_since_patch_released=45with compensating controls $\implies$ still a4.2(a)breach. - Confirm MFA scoping: a non-critical asset with no internet customer-information access and no MFA $\implies$ compliant, with
MULTI_FACTOR_AUTHinnot_applicable_requirements; a non-critical asset that accesses customer information over the internet withoutmfa_on_customer_information_accounts$\implies$4.6(b)breach;is_critical_system=None$\implies$ audited conservatively as in scope. - Confirm the 4.3 and 4.5 carve-outs: non-conformance with
nonconformity_controls_in_place=True$\implies$ compliant with a4.3(c)warning; absent malware protection with a non-blank justification $\implies$ compliant with a4.5warning, but a blank justification $\implies$4.5breach. - Confirm the gate fails closed: blank identifiers, an unknown severity, a negative or boolean
days_since_patch_released, a list (rather than tuple) of vulnerabilities, duplicate vulnerability IDs, an unknownentity_class, and a missingpatch_policymust each raise. An asset built from identifiers alone must audit non-compliant. - Confirm the audit trail is complete: an asset failing everything must carry all six requirements in
failed_requirementsand seven breached paragraphs, withremediation_progress_pct == 0.0. - Run the test suite:
python -m unittest discover -s skills/singapore-mas-notice-on-cyber-hygiene-for-trading-systems/scripts