| # Security Policy |
| |
| Apache Wicket follows the [Apache Software Foundation security process](https://www.apache.org/security/). |
| |
| ## Reporting a Vulnerability |
| |
| **Please do not report security vulnerabilities through GitHub issues, GitHub |
| discussions, pull requests, JIRA, or the public mailing lists.** Doing so |
| discloses the issue publicly before a fix is available. |
| |
| Report suspected vulnerabilities privately to: |
| |
| - **security@apache.org** — the ASF Security Team, who will forward the report |
| to the Wicket PMC. |
| |
| A useful report includes: |
| |
| - the affected Wicket version(s) and the module (e.g. `wicket-core`), |
| - the affected class and method, ideally with a source reference, |
| - a concrete description of how an attacker reaches the code, including what |
| the attacker is assumed to control (see [Security Model](#security-model)), |
| - the impact you believe follows from that, and |
| - a reproducer where possible — a failing test is ideal. |
| |
| Please state clearly whether you have published anything about the issue, and |
| whether you are requesting a CVE. |
| |
| We ask reporters to keep the issue confidential until a fixed release is |
| published and the PMC has announced it. In return, we will keep you informed of |
| our assessment and of the release timeline, and credit you in the announcement |
| unless you ask us not to. |
| |
| Note that reports are assessed against the scope, the two conditions in |
| [Reports We Do Not Assess](#reports-we-do-not-assess), and the security model |
| below. |
| A report that depends on the framework distrusting something this model treats |
| as trusted may be closed as a deployment or configuration issue rather than a |
| framework vulnerability. If you believe the model itself is wrong, that is a |
| legitimate and useful thing to report — please say so explicitly, so we discuss |
| the model rather than the individual code path. |
| |
| Conversely, a demonstrated bypass of a boundary this model does claim — for |
| example the package resource guard, or an authorization strategy — is a |
| vulnerability, and we want to hear about it. The boundaries below describe what |
| Wicket intends to enforce; where the code falls short of them, the code is what |
| needs fixing. |
| |
| ## Supported Versions |
| |
| Security fixes are applied to the actively maintained release lines. Refer to |
| the [download page](https://wicket.apache.org/start/download.html) for the |
| current status and the latest release of each line. |
| |
| | Version | Status | |
| | ------- | ----------------------------------------------- | |
| | 11.x | In development (`master`) — not yet released | |
| | 10.x | Current, supported | |
| | 9.x | Supported | |
| | 8.x | Security fixes only — upgrade to 9.x or 10.x | |
| | ≤ 7.x | Discontinued — no security fixes | |
| |
| If you are running a discontinued version, the fix is to upgrade. See the |
| [Migration to Wicket 10.0](https://cwiki.apache.org/confluence/display/WICKET/Migration+to+Wicket+10.0) |
| guide on our wiki, which links the guides for the earlier lines. |
| |
| ## Scope |
| |
| The table above says which release lines receive security fixes. Three |
| categories of code inside those lines sit outside this process. |
| |
| ### Deprecated code is out of scope |
| |
| `@Deprecated` is our statement that code has no future and that an application |
| should stop relying on it. Where an application has to reach that code |
| deliberately — calling a deprecated method, extending a deprecated class, |
| setting a deprecated setting — the remedy for a problem in it is to stop using |
| it, not to harden something we intend to remove. Such a report is closed with a |
| pointer to whatever the migration is; it receives no CVE, and the deprecated |
| code is not fixed. |
| |
| Two limits on that, both of which cut in the reporter's favour: |
| |
| - **Deprecation is per release line.** A member deprecated on `master` may still |
| be current in 10.x or 9.x. A report is judged against the line it targets, not |
| against `master`. |
| - **Deprecating a member does not deprecate the behaviour behind it.** Where a |
| deprecated accessor merely fronts a feature that is still current and still |
| reachable without the application opting in, the feature is in scope and the |
| deprecated accessor is beside the point. What this section excludes is |
| functionality an application chooses to use, not behaviour it gets whether it |
| asks for it or not. |
| |
| Where something is deprecated *because* it is insecure, the javadoc says so. |
| Usually it also names what to use instead. Sometimes it cannot: where the design |
| rather than the implementation is the problem, a feature may be one that cannot |
| be made safe, and we will deprecate it with no replacement offered — the secure |
| course is to stop doing the thing at all rather than to do it differently, so |
| there is nothing to migrate to. Deprecation is the fix in that case, and the code |
| is out of scope on the same footing as any other deprecated code. The javadoc |
| says which of the two applies, so it is clear before reporting. |
| |
| ### `OriginResourceIsolationPolicy` is out of scope |
| |
| Wicket ships two `IResourceIsolationPolicy` implementations, and only one of them |
| carries the boundary described in |
| [Another origin may not invoke a listener](#another-origin-may-not-invoke-a-listener). |
| |
| `FetchMetadataResourceIsolationPolicy`, added in 9.1.0, is the supported one. It |
| reads the `Sec-Fetch-*` request headers, which the browser sets and which page |
| content can neither forge nor remove. |
| |
| `OriginResourceIsolationPolicy` is the older mechanism, kept so that |
| `ResourceIsolationRequestCycleListener` still has something to say about a client |
| that does not send those headers. It compares the `Origin` and `Referer` headers |
| against the requested URL, and the limits of that approach are inherent in the |
| headers rather than in the implementation: |
| |
| - **Neither header need arrive.** Browsers send `Origin` on a form submit, but |
| not on a plain GET — which is how a `Link` and most Ajax behaviours invoke their |
| listener. There the check falls back to `Referer`, and `Referer` is suppressed |
| by the referring page's own `Referrer-Policy`, by `rel="noreferrer"`, and by an |
| HTTPS-to-HTTP downgrade. The document on the other origin chooses its own |
| referrer policy, so it is the party deciding whether a source header reaches us |
| at all. |
| - **A missing source is not a rejection.** With no usable header the outcome is |
| `UNKNOWN` and the request is settled by |
| `ResourceIsolationRequestCycleListener#setUnknownOutcomeAction`, which defaults |
| to aborting — but which deployments relax precisely because legitimate traffic |
| also arrives without the headers. |
| - **It cannot express the boundary.** The policy ignores the `RequestType`, so it |
| cannot distinguish a page render, which may legitimately be a top-level |
| navigation from another site, from a listener invocation, which may not. |
| - **Its idea of the target is the trusted host.** It builds the URI it compares |
| against from the container-reported host, port and scheme (see |
| [Wicket trusts the container-reported host, port and scheme](#wicket-trusts-the-container-reported-host-port-and-scheme)), |
| and `addAcceptedOrigin` matches subdomains, so accepting a domain accepts every |
| host beneath it. |
| |
| We therefore do not assess a report that a request can get past this policy, and |
| we will not harden it. The remedy is `FetchMetadataResourceIsolationPolicy`, which |
| is what the framework claims; a deployment that does not want the fallback at all |
| can construct the listener without it: |
| `new ResourceIsolationRequestCycleListener(new FetchMetadataResourceIsolationPolicy())`. |
| The class is not marked `@Deprecated` only because it remains a reasonable |
| fallback for a legacy client, where the alternative is to refuse the request |
| outright. |
| |
| What this exclusion does not cover is the chain around it. The default policy list |
| is `FetchMetadataResourceIsolationPolicy` followed by |
| `OriginResourceIsolationPolicy`, checked in order, and the first policy to return |
| an outcome other than `UNKNOWN` decides. A request carrying `Sec-Fetch-Site` is |
| consequently always settled by the fetch-metadata policy and never reaches the |
| origin policy, and another document cannot make a browser omit that header. So a |
| report showing that a request *with* `Sec-Fetch-Site` present is nonetheless |
| decided by the origin policy is in scope, as is anything else in |
| `ResourceIsolationRequestCycleListener` itself. |
| |
| **8.x has no supported resource isolation implementation.** The |
| `IResourceIsolationPolicy` mechanism arrived in 9.1.0. On 8.x the only |
| cross-origin check Wicket offers is `CsrfPreventionRequestCycleListener`, which |
| reads the same two headers with the same limits; 9.x deprecates it in favour of |
| the resource isolation listener and it is therefore already out of scope there |
| under [Deprecated code is out of scope](#deprecated-code-is-out-of-scope), while |
| on 8.x it is not deprecated only because that line has nothing to migrate to. An |
| 8.x application that needs anything stronger has to upgrade or implement the check |
| itself: we will not backport the fetch-metadata policy, and reports against |
| `CsrfPreventionRequestCycleListener` are out of scope on the same footing as the |
| origin policy. |
| |
| ### `wicket-examples` is sample code, not production code |
| |
| `wicket-examples` exists to demonstrate framework features in as few lines as |
| possible. It is not written to production standards, and some of it is |
| deliberately insecure so that the examples run anywhere out of the box. |
| `WicketExampleApplication`, the base class of every example, installs `NoCrypt` |
| as the crypt factory — a no-op cipher, so that nothing depends on the local JCE |
| setup — and enables the development utilities; the source says in as many words |
| not to do either in a real application. Individual examples go further: |
| `authentication1` hardcodes its one credential pair in the source. Do not read |
| the examples as a security reference, and do not copy them into an application |
| unchanged. |
| |
| We do want to hear about problems in them, because example code gets copied and |
| a misleading pattern propagates from there into real applications. But fixing |
| one is a correction to teaching material rather than a fix to a vulnerability in |
| the framework, so: |
| |
| - the PMC will not request a CVE for it; |
| - it is fixed on `master` only. `wicket-examples` ships as a WAR in every |
| release, and we knowingly leave the released examples as they are; |
| - once we have confirmed the problem is example-only, it is tracked in public |
| [JIRA](https://issues.apache.org/jira/projects/WICKET), since there is nothing |
| to embargo. |
| |
| The same reasoning covers `wicket-devutils`, a development aid rather than a |
| production module (see |
| [Deployment configuration](#deployment-configuration-is-the-operators-responsibility)), |
| and the internal test modules that are never published. It does **not** cover |
| `wicket-tester` or `wicket-extensions-tester`, which are released artifacts that |
| applications depend on, and it does not cover the quickstart archetype: |
| applications are started from the archetype, so it is expected to be secure by |
| default and is in scope like any other module. |
| |
| The examples are also hosted publicly by the ASF. Those deployments are ASF |
| infrastructure, not a Wicket release. If you find something that affects the |
| hosting rather than the example application itself, it is still worth reporting |
| to **security@apache.org** — say that it concerns the hosted site, so that it can |
| be routed to ASF Infrastructure as well as to the PMC. |
| |
| ## Reports We Do Not Assess |
| |
| The two conditions below are about the report rather than about the code. Both |
| exist because a report that cannot be verified costs as much to triage as one |
| that can, and neither is a judgement on whether the concern behind it is real. |
| |
| ### A finding must be verified against a supported branch tip |
| |
| Verify the issue against the current tip of the line you are reporting against: |
| `wicket-8.x`, `wicket-9.x`, `wicket-10.x`, or `master`. One of them is enough — |
| say which, and name the commit you tested. A failing test against that commit is |
| ideal. Reporting only the release you happen to be running is not sufficient: a |
| released artifact is always behind its branch, and what you found may already be |
| fixed there. |
| |
| We do not assess a report verified only against an older version. A release that |
| is not its branch tip may be missing fixes that are already public, and the |
| discontinued lines — 7.x and earlier — receive no security fixes at all, so the |
| remedy there is to upgrade whether or not the behaviour you found is a |
| vulnerability. Note also that git branches exist for every line Wicket has ever |
| shipped; a branch existing is not a statement that the line is supported. The |
| table above is. |
| |
| Before reporting, check the advisories already published for the line you tested, |
| at [security.apache.org/projects/wicket/](https://security.apache.org/projects/wicket/). |
| An issue fixed in a later release of that same line is not a vulnerability |
| report; it is a reason to upgrade. |
| |
| This is a condition on the evidence, not on the finding. If the behaviour does |
| reproduce on a supported tip, re-verify it there and send it again — arriving |
| first against the wrong version is not held against a report. |
| |
| ### A report must refer to code that exists |
| |
| We do not assess a report whose subject cannot be found in the codebase: a class, |
| method, setting, or file that does not exist on the branch the report names. Such |
| a report cannot be confirmed or ruled out, and there is nothing in it for us to |
| fix. |
| |
| Quote the code you are describing, from the branch you are targeting, and give |
| paths as they appear in the repository. Where a reference is merely inaccurate — |
| the right class named under the wrong module, a line number that has moved since |
| you looked — we will resolve it ourselves and say so. What we close unassessed is |
| a report whose subject is not in the code at all: a method that was never |
| written, a field given a value it does not have, a call chain whose steps do not |
| exist. |
| |
| How the report was produced does not matter to us: by hand, with tooling, or |
| with a model. Accuracy is what matters. A report whose subject we cannot locate |
| is indistinguishable from a real finding until every claim in it has been checked |
| against the code, and that is effort we would rather spend on the reports that |
| hold up. Tell us what you verified and where you verified it, and we will take it |
| from there. |
| |
| ## Security Model |
| |
| Wicket is a framework, not a deployed application. It runs inside a servlet |
| container, usually behind a reverse proxy, and it inherits its view of the |
| outside world from that container. This section documents which of those inputs |
| Wicket treats as trusted, so that operators know what they are responsible for |
| and reporters know what the framework does and does not claim to defend. |
| |
| ### Wicket trusts the container-reported host, port and scheme |
| |
| Wicket derives its own public identity — the scheme, host and port it believes |
| it is being served on — from the servlet container, via |
| `HttpServletRequest#getScheme()`, `#getServerName()` and `#getServerPort()`. |
| There is no hostname allowlist in the framework and no attempt to verify the |
| `Host` header, in any of the places this identity is used: |
| |
| - `ServletWebRequest#setParameters` sets the host, port and protocol on the |
| client URL from these three values. That URL backs `UrlRenderer`, and so |
| every absolute URL Wicket renders. |
| - `HttpsMapper#createRedirectUrl` builds the scheme-switch redirect for |
| `@RequireHttps` pages from the same values. |
| - `OriginResourceIsolationPolicy#getTargetUriFromRequest` builds the **trusted** |
| target URI that incoming `Origin` and `Referer` headers are compared against. |
| |
| This is a deliberate design decision, not an oversight. Only the deployment |
| knows its own canonical hostnames; the framework cannot infer them. Note in |
| particular that the third item means the container-reported host is a trusted |
| input to a request-forgery defence — a deployment that lets arbitrary `Host` |
| values through weakens more than URL rendering. That policy is the legacy one and |
| is [out of scope](#originresourceisolationpolicy-is-out-of-scope); |
| `FetchMetadataResourceIsolationPolicy`, the supported one, does not consult the |
| host at all. |
| |
| **Therefore the deployment is responsible for ensuring that only expected |
| `Host` values reach the application.** Concretely: |
| |
| 1. Configure the container or virtual host to reject requests carrying an |
| unrecognised `Host` — return a 400 or 404 rather than routing them to the |
| application. Tomcat, Jetty and the common reverse proxies all support this. |
| 2. If TLS is terminated at a proxy, have the proxy set or overwrite `Host` to |
| the canonical name rather than forwarding whatever the client sent. |
| 3. Do not expose a Wicket application through a catch-all or default virtual |
| host that accepts any `Host`. |
| 4. Serve the application over HTTPS and enable HSTS, so that plaintext requests |
| — including the ones `HttpsMapper` exists to upgrade — are not part of the |
| normal flow. |
| |
| A consequence worth stating plainly: on a deployment that accepts arbitrary |
| `Host` values, absolute URLs and redirects generated by Wicket will contain the |
| host the client supplied. That is the documented behaviour of trusting the |
| container. It is not treated as a framework vulnerability, because the host in |
| such a response is always the same authority the client had already connected |
| to — it grants an attacker no origin they did not already control. The fix |
| belongs at the container or proxy, per the points above. |
| |
| ### `X-Forwarded-*` headers are not trusted by default |
| |
| Wicket ignores `X-Forwarded-For` and `X-Forwarded-Proto` unless you explicitly |
| enable `XForwardedRequestWrapperFactory`. When enabled, it overrides |
| `getRemoteAddr()`, `getRemoteHost()`, `getScheme()` and `getServerPort()` from |
| those headers, subject to its `allowedInternalProxies` and `trustedProxies` |
| configuration. |
| |
| Only enable it when a trusted proxy in front of the application appends to |
| these headers and strips any client-supplied copies; otherwise the headers are |
| attacker-controlled. Wicket does not implement `X-Forwarded-Host` at all, and |
| `XForwardedRequestWrapper` does not override `getServerName()` — the host always |
| comes from the container as described above. |
| |
| ### Client-supplied URLs are not trusted for authority |
| |
| For Ajax requests Wicket reads a client-supplied base URL — the |
| `Wicket-Ajax-BaseURL` header, falling back to the `wicket-ajax-baseurl` request |
| parameter — in order to resolve relative URLs against the page the client is |
| actually on. The host, port and protocol of that URL are always overwritten with |
| the container-reported values before use. The client can influence the path |
| Wicket renders relative to, never the authority. |
| |
| ### Deployment configuration is the operator's responsibility |
| |
| `RuntimeConfigurationType.DEVELOPMENT` enables debugging aids, verbose error |
| reporting and development-only components, and disables some caching. It is not |
| intended for production and is not hardened. Always run production deployments |
| with the configuration type set to `RuntimeConfigurationType.DEPLOYMENT`. Issues |
| only reachable in `DEVELOPMENT` mode are treated as configuration errors rather |
| than vulnerabilities. |
| |
| Likewise, `wicket-devutils` is a development aid. Do not deploy it in |
| production; it is out of scope for the same reason the examples are (see |
| [Scope](#scope)). |
| |
| ### Serialized data is trusted |
| |
| Wicket serializes page instances and session data to its page store. Java |
| deserialization is not a safe operation on untrusted input, and by default |
| Wicket's page store does not defend against it. Treat the page store and the |
| session store as trusted, private storage: do not point them at storage that |
| untrusted parties can write to, and do not accept externally supplied |
| serialized page or session data. |
| |
| The partial exception is a page store configured with encryption |
| (`StoreSettings#setEncrypted(true)`). Every `ICryptScheme` Wicket ships is |
| authenticated (AEAD), so encrypted pages are tamper-evident as well as |
| confidential: modified or substituted bytes fail to decrypt and the page is |
| treated as absent instead of being handed to the deserializer. Each page is |
| additionally bound to the page id it was stored under, so a stored page cannot |
| be replayed as a different one. The scheme marker prefixing each ciphertext is |
| authenticated too, and is refused unless it is one of the schemes accepted by |
| `SecuritySettings#setWhitelistedCryptSchemes`, so an attacker cannot force |
| decryption with a weaker scheme. |
| |
| Three limits on that exception are worth stating. The key lives in the user's |
| session, so this protects the stored pages against a party who can read or |
| write the store, not against one who already controls the session. It covers |
| the page store only — the container's session store, and anything else holding |
| serialized Wicket data, remains trusted storage. And a custom `ICryptScheme` |
| inherits the guarantee only if it honours the contract: `decrypt` must return |
| `null` on authentication failure rather than returning unverified plaintext. |
| |
| ### Model data is escaped; markup and message bundles are trusted |
| |
| Wicket escapes the text a component renders from its model. `Component`'s |
| `escapeModelStrings` flag is **on by default**, and a component renders |
| model-derived text either through `Component#getDefaultModelObjectAsString()` or |
| by applying `Strings#escapeMarkup` when that flag is set. A component that writes |
| application model data into the markup unescaped in the default configuration is |
| a bug in the framework and an opening for cross-site scripting (XSS). We want to |
| hear about it. |
| |
| `setEscapeModelStrings(false)` is the application saying the content is markup |
| and taking responsibility for it. Reports that depend on an application having |
| cleared the flag are configuration issues rather than framework vulnerabilities. |
| Note that a few components clear it themselves because their value is written |
| into an attribute, which is escaped when the tag is written and would otherwise |
| be encoded twice; that is an implementation detail of those components and not an |
| invitation to render untrusted markup through them. |
| |
| Two inputs on the other side of the boundary are trusted, because both are |
| authored by the developer and neither is data the application received at |
| runtime: |
| |
| - **Markup files are trusted.** A `.html` file on the classpath is a template, |
| exactly like a JSP or a Thymeleaf template, and Wicket renders it as markup. An |
| application that serves markup from somewhere an untrusted party can write — |
| through a custom `IMarkupResourceStreamProvider`, for instance — has taken |
| that trust on itself. |
| - **Message bundles are trusted.** `<wicket:message key="…"/>` renders its |
| property value as markup by default, and `escape="true"` opts in to escaping. |
| Markup in a bundle is therefore a supported way to format a message. |
| |
| The value a bundle string interpolates is a different matter. `${name}` in a |
| message resolves first to a child component with `wicket:id="name"`, whose |
| rendered markup carries that component's own escaping. Only when there is no |
| such child does Wicket fall back to reading `name` from the surrounding |
| component's model, and that value is written as it came — so a static bundle can |
| still place model data in the markup unescaped. Prefer the child component. |
| Where the fallback is unavoidable and the data is not trusted, the message needs |
| `escape="true"`, which escapes the whole message and therefore any markup the |
| bundle itself contains. |
| |
| Finally, `Strings#escapeMarkup` escapes `<`, `>`, `&`, `"` and `'`. That is |
| enough for element text and for a quoted attribute value, and it is not enough |
| for anything else: it does not make a value safe inside `<script>` or `<style>`, |
| in an unquoted attribute, or in a URL where the scheme itself is the payload. |
| Wicket does not automatically escape a value the application places into a |
| JavaScript context — through `TextTemplate` variable substitution, for example — |
| so the application has to encode it. |
| |
| ### Another origin may not invoke a listener |
| |
| Where `ResourceIsolationRequestCycleListener` is registered, a request originating |
| from another origin must not be able to invoke a listener on a page — a |
| `Link.onClick()`, a `Form.onSubmit()`, or an AJAX behaviour. A demonstrated way |
| for another origin to reach one is a vulnerability. |
| |
| Two things sit deliberately outside that boundary: |
| |
| - **Rendering a page is allowed.** A page may be reached by a simple top-level |
| navigation from anywhere, so that pages remain linkable from other sites. Only |
| the invocation of a listener is refused. This holds for every render, not only |
| for top-level navigations: a page reached as a subresource load, through |
| `fetch`, or inside an `<object>` or `<embed>` is not refused either, because |
| the listener does not consult a policy for renders at all. A page whose render |
| alone discloses something sensitive cannot rely on this listener. |
| - **Sibling origins may be trusted explicitly.** `Sec-Fetch-Site: same-site` |
| means a different origin on the same registrable domain and scheme, such as |
| another subdomain, and is refused by default. A deployment that trusts every |
| origin on its own site can allow it; sibling-origin actions are then that |
| deployment's decision rather than a framework vulnerability. |
| |
| The boundary is `FetchMetadataResourceIsolationPolicy`'s. The listener also |
| consults `OriginResourceIsolationPolicy` by default, for clients that send no |
| `Sec-Fetch-*` headers, and that policy is |
| [out of scope](#originresourceisolationpolicy-is-out-of-scope). |
| |
| This listener is opt-in and is not registered by default. Without it Wicket |
| enforces no cross-origin boundary on listener invocation at all. `CryptoMapper` |
| raises the cost of forging a URL but is not a substitute for it, for the reason |
| below. |
| |
| ### `CryptoMapper` is not an authorization mechanism |
| |
| `CryptoMapper` encrypts URLs so that page and component identifiers are not |
| guessable. It raises the cost of forging a URL, but it is not an access-control |
| mechanism. Authorization must be enforced with `IAuthorizationStrategy` (or |
| equivalent) so that it holds regardless of whether a URL was guessed, |
| replayed, leaked through a referrer, or found in a log. |
| |
| ### Encrypted URLs are deterministic by design |
| |
| `CryptoMapper` encrypts a URL to the same text every time, for as long as the |
| key lives. It has to: a URL regenerated during rendering must match the one the |
| client requested, and a resource URL must stay identical across requests or the |
| browser re-downloads the resource on every page view. The consequence is that |
| equal URLs are recognisable as equal, and that anyone holding the key can |
| confirm a guessed URL by encrypting it themselves. With the default |
| `KeyInSessionCryptFactory` the key is per session, so this is confined to a |
| single user; with an application-wide key it is not. Encrypted URLs are |
| therefore an obfuscation and a per-session CSRF token, never a secret in their |
| own right — which is the same reason they are not an authorization mechanism. |
| Everything Wicket encrypts elsewhere, such as the page store, uses the randomized |
| path and does not have this property. |
| |
| ## Reporting Something That Is Not a Vulnerability |
| |
| Findings that are real but not vulnerabilities are still welcome — please raise |
| them publicly in [JIRA](https://issues.apache.org/jira/projects/WICKET) or as a |
| pull request rather than through the private security channel, so they can be |
| discussed and fixed in the open. Hardening suggestions, defence-in-depth |
| improvements, and clarifications to this document all fall into that category. |
| |
| If you are unsure which channel applies, use the private one — we would rather |
| receive a non-issue privately than a real issue publicly. |