Ben Weidig created TAP5-2835:
--------------------------------

             Summary: JavaScript source mapes (*.map) shouldn't be served by 
default when running in production mode
                 Key: TAP5-2835
                 URL: https://issues.apache.org/jira/browse/TAP5-2835
             Project: Tapestry 5
          Issue Type: Improvement
          Components: tapestry-core
    Affects Versions: 5.9.1
            Reporter: Ben Weidig


h2. Problem

Even though Tapestry doesn't generate sources maps, there are possible maps to 
be found in most projects:
 * build artifact copied into {{META-INF/assets}} or {{META-INF/modules}} 
alongside the application's compiled/bundled JS
 * vendored third-party bundle + map dropped into the webapp context and 
referenced via the {{context:}} prefix 
(e.g.{{{}@Path("context:js/vendor.min.js"){}}}).

In production, these maps let anyone reconstruct original, unminified (and 
potentially unobfuscated/uncommented) source from the shipped bundle simply by 
requesting {{{}<bundle>.js.map{}}}.
h2. Proposed Solution

Introduce a new {{ContextAssetProtectionRule}} chain-of-responsibility service, 
mirroring the existing {{{}ClasspathAssetProtectionRule{}}}.
Both are ordered-configuration chains where any contributed rule returning true 
for a path blocks the request (handler returns 404).
 * {{ContextAssetRequestHandler}} consults an injected 
{{ContextAssetProtectionRule}}
 * {{ClasspathAssetRequestHandler}} already had this mechanism, no change to 
the handler itself.
 * {{AssetsModule}} contributes a {{SourceMapFile}} rule to both chains, 
blocking any path ending in {{{}.map{}}}, gated on 
{{{}@Symbol(TapestryHttpSymbolConstants.PRODUCTION_MODE){}}}. The rule is only 
added when production mode is active, so development/QA environments are 
unaffected.

Because both rules are ordinary IoC contributions, applications retain full 
control.

*Note:* the {{asset:}} prefix resolves to a path under {{META-INF/assets/}} on 
the classpath and is served through {{{}ClasspathAssetRequestHandler{}}}.
It is therefore already covered by the {{ClasspathAssetProtectionRule}} chain 
and needs no separate handling.
h2. Caveat

The new chain for {{ContextAssetRequestHandler}} won't change the existing 
behaviour and filter out {{{}WEB-INF{}}}, {{{}META-INF{}}}, and {{*.tml}} files.
These rules are non-negotiable regardless of production mode.
h2. Risks
h3. Behavioral change for existing apps

Any application currently relying on .map files being served in production will 
see those requests start returning 404 after upgrading.
h5. Mitigation

Documented as an intentional default.
Recoverable via a one-line 
{{{}ContextAssetProtectionRule{}}}/{{{}ClasspathAssetProtectionRule{}}} 
contribution override, and behavior is unchanged in development mode.
h3. Rule scope is extension-based, not content-based

The block is a simple {{.toLowerCase().endsWith(".map")}} check.
Any legitimate, non-source-map asset that happens to use a {{.map}} extension 
would also be blocked in production under the default rule.
h5. Mitigation

Same override path as above.
h3. Two independent rule chains

Because context and classpath assets now have separate protection mechanisms, 
an app overriding one (e.g., to re-enable maps under {{{}context:{}}}) must 
remember the other chain ({{{}classpath:{}}}) still blocks them by default, and 
vice versa.



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to