/**
 * @name Missing X-Frame-Options HTTP header
 * @description If the 'X-Frame-Options' setting is not provided, a malicious user may be able to
 *              overlay their own UI on top of the site by using an iframe.
 * @kind problem
 * @problem.severity error
 * @precision high
 * @id cs/web/missing-x-frame-options
 * @tags security
 *       external/cwe/cwe-451
 *       external/cwe/cwe-829
 */

import csharp
import semmle.code.asp.WebConfig
import semmle.code.csharp.frameworks.system.Web

/**
 * Holds if there exists a `Web.config` file in the snapshot that adds an `X-Frame-Options` header.
 */
predicate hasWebConfigXFrameOptions() {
  /*
   * Looking for an entry in a Web.config file that looks like this:
   * ```
   * <system.webServer>
   *   <httpProtocol>
   *    <customHeaders>
   *      <add name="X-Frame-Options" value="SAMEORIGIN" />
   *    </customHeaders>
   *   </httpProtocol>
   * </system.webServer>
   * ```
   */
  exists(XMLElement element |
    element = any(WebConfigXML webConfig).getARootElement().getAChild("system.webServer").getAChild("httpProtocol").getAChild("customHeaders").getAChild("add") |
    element.getAttributeValue("name") = "X-Frame-Options"
  )
}

/**
 * Holds if there exists a call to `AddHeader` or `AppendHeader` adding the `X-Frame-Options`
 * header.
 */
predicate hasCodeXFrameOptions() {
  exists(MethodCall call |
    call.getTarget() = any(SystemWebHttpResponseClass r).getAppendHeaderMethod() or
    call.getTarget() = any(SystemWebHttpResponseClass r).getAddHeaderMethod() |
    call.getArgumentForName("name").getValue() = "X-Frame-Options"
  )
}

from WebConfigXML webConfig
where not hasWebConfigXFrameOptions()
  and not hasCodeXFrameOptions()
select webConfig, "Configuration file is missing the X-Frame-Options setting."
