// CWE-942: CORS misconfiguration — wildcard origin or credentials without origin restriction.
// Only activated when mocket or crescent is imported.

///|
priv struct Cwe942Visitor {
  findings : Array[Finding]
  file : String
  source : String
}

///|
pub fn cwe942_info() -> RuleInfo {
  {
    id: { cwe: 942, variant: "cors-credentials" },
    name: "Permissive CORS Configuration",
    description: "handle_cors() without explicit origin defaults to '*', allowing any website to read responses. With credentials=true this enables credential theft.",
    default_severity: Warning,
  }
}

///|
pub fn run_cwe942(
  impls : @list.List[@syntax.Impl],
  file : String,
  source : String,
  findings : Array[Finding],
  severity : Severity,
) -> Unit {
  let _ = severity
  let visitor : Cwe942Visitor = { findings, file, source }
  impls.each(fn(impl_) { @syntax.IterVisitor::visit_Impl(visitor, impl_) })
}

///|
fn is_cors_func(func : @syntax.Expr) -> Bool {
  match func {
    Ident(id~, ..) =>
      match id.name {
        Ident(name="handle_cors")
        | Ident(name="append_cors_preflight_headers")
        | Ident(name="append_cors_headers") => true
        Dot(id="handle_cors", ..)
        | Dot(id="append_cors_preflight_headers", ..)
        | Dot(id="append_cors_headers", ..) => true
        _ => false
      }
    _ => false
  }
}

///|
impl @syntax.IterVisitor for Cwe942Visitor with fn visit_Expr_Apply(
  env,
  func~,
  args~,
  loc~,
) {
  if is_cors_func(func) {
    let has_explicit_origin = match get_labelled_string_value(args, "origin") {
      Some(v) => v != "*"
      None => false
    }
    if !has_explicit_origin {
      let has_credentials_true = has_labelled_bool_arg(
        args, "credentials", true,
      )
      // Only flag when credentials=true with wildcard — that's the real attack vector.
      // Wildcard without credentials is standard for public APIs.
      if has_credentials_true {
        env.findings.push(
          make_finding(
            { cwe: 942, variant: "cors-credentials" },
            Error,
            High,
            "CORS with credentials=true and wildcard origin allows any website to make authenticated requests and read responses. Specify an explicit origin.",
            env.file,
            env.source,
            loc,
          ),
        )
      }
    }
  }
  @syntax.IterVisitor::base(env).visit_Expr_Apply(func~, args~, loc~)
}