コード

bot/index.js

visit() を呼んでいる

// ...
app.post("/api/report", async (req, res) => {
  const { path } = req.body;
  if (typeof path !== "string") {
    return res.status(400).send("Invalid path");
  }
  const url = APP_URL + path;

  try {
    await visit(url);
    return res.send("OK");
// ...

bot/bot.js

const FLAG = process.env.FLAG ?? "Alpaca{DUMMY}";
/^Alpaca\{[A-Z]{1,6}\}$/.test(FLAG) || (() => { throw new Error("Invalid FLAG format"); })();

// ...
export const visit = async (url) => {
// ...
    const page = await browser.newPage();
    await page.setCookie({
      name: "FLAG",
      value: FLAG,
      domain: new URL(APP_URL).hostname,
      path: "/",
    });
    await page.goto(url, { timeout: 5000 });
 // ...

web/app.py

@app.after_request
def set_csp(response):
    # CSP Specification: <https://www.w3.org/TR/CSP3/>
		# ...

    response.headers["Content-Security-Policy"] = (
        "default-src 'none'; "
        "script-src 'none'; "
        "style-src 'self' 'unsafe-inline'; "
        "object-src 'none'; "
        "base-uri 'none'; "
        "frame-ancestors 'none'; "
        "frame-src 'none'; "

        # This might be a good idea for exfiltration ;)
        "img-src *; "
    )

    return response
INDEX = """
# ...
    <style>
         artwork 
    </style>
</head>
<body>
    <div class="artwork-container">
        <div class="plaque plaque-top">
            <span class="flag" data-flag=" flag ">Flag:  flag </span>
        </div>
@app.get("/")
def index():
    artist = request.args.get("artist", "bubu")
    title = request.args.get("title", "my best friend")
    artwork = request.args.get("artwork", "\n".join(open("./static/example.css").readlines()))
    # Flag format: Alpaca{[A-Z]{1,6}}
    flag = request.cookies.get("FLAG", "Alpaca{DUMMY}")
    return render_template_string(INDEX, artist=artist, title=title, artwork=artwork, flag=flag)

🤔

solve